我想做这样的事情:
#define EQ4(a_,b_) (*(int*)(a_)==*(int*)(b_))
char *s1 = "food";
char *s2 = "fred";
return EQ4(s1,s2);
但是gcc正在产生这个警告:警告:解除引用类型惩罚指针会破坏严格别名规则。
由于我没有将解除引用的指针指定给指针变量,因此我认为我所做的事情并不是为了严格别名的目的而取消引用。
我试过了:
#define EQ4(a_,b_) (*(const int const *)(a_)==*(const int const*)(b_))
没有任何区别。
redhat linux版本2.6.32-220,gcc版本= 4.4.6
有没有办法使用严格别名警告,但仍然可以这样做?
谢谢!
修改
这些不起作用:
#define EQ4(a_,b_) (*(int*)(char*)(a_)==*(int*)(char*)(b_))
#define EQ4(a_,b_) (*(int*)(void*)(a_)==*(int*)(void*)(b_))
#define EQ4(a_,b_) (*(int* __attribute__((__may_alias__)))(a_)== \
*(int* __attribute__((__may_alias__)))(b_))
这有效:
typedef union bork { char a[4], int n32 } __attribute__((__may_alias__)) TBork;
#define EQ4(a_,b_) ((TBork*)(a_)->n32==(TBork*)(b_)->n32)
你们都怎么看待这个?
答案 0 :(得分:2)
警告是因为不保证字符串的对齐方式与声明整数变量时的方式相同。因此,当CPU需要获取整数值时,您可能会降低它的效率(因此警告)。
你可以从整数开始:
int a;
int b;
char* as=(char*)(&a);
char* bs=(char*)(&b);
as[0]='f'; as[1]='o'; ...
bs[0]='f'; bs[1]='r'; ...
return EQ4(a, b);
注意:
1)您必须确保不复制字符串的终止'\0'
字符,因为这将触及a
之外的内存(或b
})如果您提供了示例(请参阅下一个注释)
2)您必须确保您的字符串不大于您正在使用的特定平台上的int大小,否则您(再次)触摸不属于int的内存。
答案 1 :(得分:1)
在您的代码中,如果您在此情况下进行分配,则无关紧要。您的宏无论如何都会生成加载/存储指令,这些指令需要由编译器进行排序。
处理严格别名问题的一种方法是使用联合。
inline bool my_equal(char *a, char *b) {
union {
char *cPointer;
int *iPointer;
} left_union = { .cPointer = a }, right_union = { .cPointer = b };
return *left_union.iPointer == *right_union.iPointer;
}
另一种方法是使用restrict
关键字。使用此方法,您可以保证不会出现别名,编译器可以自由地按照其认为合适的方式对操作进行排序,而不会产生获得不需要的结果的风险。但是,请记住,这是一种合约编程。如果你错了,或者有人改变了程序,这可能会导致很难找到错误。