首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C克服别名限制(工会?)

C克服别名限制(工会?)
EN

Stack Overflow用户
提问于 2011-06-26 21:17:48
回答 1查看 601关注 0票数 7

假设我有一个示例源文件test.c,我正在编译它,如下所示:

$ gcc -03 -Wall

C看起来像这样..。

代码语言:javascript
复制
/// 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

我们也可以说,我接受这样的限制:如果传入两个重叠的指针,就会得到未定义的结果。

我尝试过这样的方法(假设这些宏在每一行末尾用反斜杠转义的换行符进行了适当的格式化)。

代码语言:javascript
复制
#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那里得到了“取消引用违反严格的混叠规则”的错误。

我原以为您应该使用联合以两种不同的方式正确地引用内存中的单个位置,所以接下来我尝试了这样的方法

代码语言:javascript
复制
#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进行此操作。我被混叠规则缠住了,根本没想过。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-06-26 21:44:57

编译器是正确的,因为混叠规则是由您正在访问的对象的所谓“有效类型”(即内存位置)决定的,而不考虑任何指针魔术。在这种情况下,使用联合的类型双关与显式转换没有什么不同--使用强制转换实际上更可取,因为标准并不保证任意指针类型具有兼容的表示,即您不必要地依赖于实现定义的行为。

如果要符合标准,则需要在声明原始变量时将数据复制到新变量或使用联合。

如果您的128位整数是大端或小端(即非混合端),您也可以使用memcmp() (直接或在否定返回值之后)或自己进行字节比较:通过字符类型的指针进行访问是别名规则的一个例外。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6486807

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档