1

我想做这样的事情:

#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)

大家对此怎么看?

4

2 回答 2

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(或)之外的内存(请参阅下一个注释)。 2)您必须确保您的字符串不大于您正在使用的特定平台上的 int 大小,否则您(再次)触摸不属于 int 的内存。b

于 2012-03-21T16:41:54.833 回答
1

It does not matter if you, in your code, make assignments in this case. Your macro will generate load/store instructions anyways and these need to be ordered by the compiler.

One way to deal with strict aliasing issues is to use unions.

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;
}

Another is to use the restrict keyword. Using this, you guarantee that there is no aliasing going on and the compiler is free to order the manipulations any way it sees fit without running the risk of getting unwanted results. But, keep in mind that this is a kind of contract programming. If you're wrong, or someone changes the program, this might result in hard to find bugs.

于 2012-03-21T17:06:29.613 回答