假设我有一个示例源文件 test.c,我正在编译它:
$ gcc -03 -墙
test.c 看起来像这样..
/// CMP128(x, y)
//
// arguments
// x - any pointer to an 128-bit int
// y - any pointer to an 128-bit int
//
// returns -1, 0, or 1 if x is less than, equal to, or greater than y
//
#define CMP128(x, y) // magic goes here
// example usages
uint8_t A[16];
uint16_t B[8];
uint32_t C[4];
uint64_t D[2];
struct in6_addr E;
uint8_t* F;
// use CMP128 on any combination of pointers to 128-bit ints, i.e.
CMP128(A, B);
CMP128(&C[0], &D[0]);
CMP128(&E, F);
// and so on
假设我接受这样的限制,如果你传入两个重叠的指针,你会得到未定义的结果。
我已经尝试过这样的事情(想象这些宏在每行末尾用反斜杠转义的换行符正确格式化)
#define CMP128(x, y) ({
uint64_t* a = (void*)x;
uint64_t* b = (void*)y;
// compare a[0] with b[0], a[1] with b[1]
})
但是当我在宏 (a[0] < b[0]) 中取消引用 a 时,我从 gcc 收到“取消引用破坏严格别名规则”错误
我原以为你应该使用联合以两种不同的方式正确引用内存中的一个地方,所以接下来我尝试了类似的东西
#define CMP128(x, y) ({
union {
typeof(x) a;
typeof(y) b;
uint64_t* c;
} d = { .a = (x) }
, e = { .b = (y) };
// compare d.c[0] with e.c[0], etc
})
除了我从编译器那里得到关于严格别名规则的完全相同的错误。
那么:有没有办法在不破坏严格混叠的情况下做到这一点,而不是实际复制内存?
(may_alias不算,它只是让你绕过严格的别名规则)
编辑:使用 memcmp 来做到这一点。我被混叠规则赶上了,并没有想到它。