时间结构大小检查,如果奇数出错
如果sizeof (struct Astruct)
不均匀,是否有任何可能的方式让编译器sizeof (struct Astruct)
出来?
背景信息:我们有一个16位微处理器,如果16位值不对齐,会导致处理器对齐错误。 在以下情况下可能会发生这种情况:
typedef struct
{
U8BIT u8BitValue1;
U8BIT u8BitValue2;
U8BIT u8BitValue3;
} unevenAmountOf8BitValues;
typedef struct
{
U16BIT u16BitValue1;
U16BIT u16BitValue2;
} my16BitValues;
#define U8BIT_COUNT 3
#define U16BIT_COUNT 2
typedef struct
{
unevenAmountOf8BitValues u8BitValues;
my16BitValues u16BitValues;
} valuesCombined;
typedef union
{
valuesCombined myValues;
U8BIT buffer[sizeof(valuesCombined)];
struct
{
U8BIT bufferU8[U8BIT_COUNT];
U16BIT bufferU16[U16BIT_COUNT]; /* <<-- missalignment */
} valuesPerType;
} myValuesInRamAndRom
我们现在要做的就是手动计算U8BIT / U16BIT / U32BIT值的数量(以及使用excel跟踪数量)并将其放入U(8/16/32)BIT_COUNT
,然后定义以下内容:
#if U8BIT_COUNT % 2 == 1
#error The number of U8BIT parameters need to be even, add a dummy
#endif
跟踪U8- / U16- / U32BIT值的数量是非常容易出错的,我们有很多时候我们都在想“嘿,它不工作”,一个小时或之后,哦! 该死,忘了调整数值的定义。
一个首选的方法是使用sizeof运算符,但不能用于错误检查,我真的很想保留它。
那么是否有使用sizeof运算符并保持某种形式的错误检查以确保U8BIT值的数量必须是偶数?
Lundin和Aaron McDaid的联合解决方案:
#define COMPILE_TIME_ASSERT(expr) {typedef U8BIT COMP_TIME_ASSERT[((!!(expr))*2-1)];}
使用C11编译器,请使用:
static_assert (sizeof(the struct) % 2 == 0,
"Misaligned");
使用较老的编译器,你可以使用一些肮脏的技巧
#define COMPILE_TIME_ASSERT(expr) {typedef char COMP_TIME_ASSERT[(expr) ? 1 : 0];}
...
COMPILE_TIME_ASSERT(sizeof(the_struct) % 2 == 0);
但是,针对您的特定问题的真正解决方案可能是确保启用了结构填充。 那么你不应该得到任何失调。
有可能,使用一种在Linux内核中也被使用的技巧:
#define BUILD_BUG_OR_ZERO(e) (sizeof(struct{ int:-!!(e);}))
#define ENSURE_EVEN_SIZE(e) BUILD_BUG_OR_ZERO(sizeof(e) % 2 == 1)
struct uneven{
char a,b,c;
};
struct even{
char a,b,c,d;
};
int main(){
ENSURE_EVEN_SIZE(struct even);
/* compiler error: */
ENSURE_EVEN_SIZE(struct uneven);
}
如果sizeof(e) % 2 == 1
为真,则位域int:-!!(e)
将具有负尺寸,这是禁止的。 (Ideone)
这是允许在同一个文件中多次使用相同的断言宏的版本。
/*
General purpose static assert.
Works in/out -side of scope:
STATIC_ASSERT(sizeof(long)==8);
int main()
{
STATIC_ASSERT(sizeof(int)==4);
}
*/
#define STATIC_ASSERT(X) STATIC_ASSERT2(X,__LINE__)
/*
These macros are required by STATIC_ASSERT to make token pasting work.
Not really useful by themselves.
*/
#define STATIC_ASSERT2(X,L) STATIC_ASSERT3(X,L)
#define STATIC_ASSERT3(X,L) STATIC_ASSERT_MSG(X,at_line_##L)
/*
Static assertion with special error message.
Note: It depends on compiler whether message is visible or not!
STATIC_ASSERT_MSG(sizeof(long)==8, long_is_not_eight_bytes);
*/
#define STATIC_ASSERT_MSG(COND,MSG)
typedef char static_assertion_##MSG[(!!(COND))*2-1]
链接地址: http://www.djcxy.com/p/73555.html