假设我有一个示例源文件test.c,我正在编译它,如下所示:
$ gcc -03 -Wall
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 < b)中的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进行此操作。我被混叠规则缠住了,根本没想过。
发布于 2011-06-26 21:44:57
编译器是正确的,因为混叠规则是由您正在访问的对象的所谓“有效类型”(即内存位置)决定的,而不考虑任何指针魔术。在这种情况下,使用联合的类型双关与显式转换没有什么不同--使用强制转换实际上更可取,因为标准并不保证任意指针类型具有兼容的表示,即您不必要地依赖于实现定义的行为。
如果要符合标准,则需要在声明原始变量时将数据复制到新变量或使用联合。
如果您的128位整数是大端或小端(即非混合端),您也可以使用memcmp() (直接或在否定返回值之后)或自己进行字节比较:通过字符类型的指针进行访问是别名规则的一个例外。
https://stackoverflow.com/questions/6486807
复制相似问题