Tag: strict aliasing

为什么编译器不再使用严格的别名来优化此UB

谷歌严格别名的第一个结果之一就是这篇文章http://dbp-consulting.com/tutorials/StrictAliasing.html 我注意到的一件有趣的事情是: http : //goo.gl/lPtIa5 uint32_t swaphalves(uint32_t a) { uint32_t acopy = a; uint16_t* ptr = (uint16_t*)&acopy; uint16_t tmp = ptr[0]; ptr[0] = ptr[1]; ptr[1] = tmp; return acopy; } 被编译为 swaphalves(unsigned int): mov eax, edi ret 由GCC 4.4.7。 任何比这更新的编译器(文章中提到的4.4所以文章没有错)都没有实现该函数,因为它可以使用严格别名。 这是什么原因? 它实际上是GCC中的错误还是GCC决定放弃它,因为许多行代码是以产生UB的方式编写的,或者它只是一个持续多年的编译器回归…而Clang也没有优化它。

这种有效类型规则的使用是否严格符合?

C99和C11中的有效类型规则规定,可以使用任何类型写入没有声明类型的存储,并且存储非字符类型的值将相应地设置存储的有效类型。 撇开INT_MAX可能小于123456789的事实,以下代码对有效类型规则的使用是否严格符合? #include #include /* Performs some calculations using using int, then float, then int. If both results are desired, do_test(intbuff, floatbuff, 1); For int only, do_test(intbuff, intbuff, 1); For float only, do_test(floatbuff, float_buff, 0); The latter two usages require storage with no declared type. */ void do_test(void *p1, void *p2, int leave_as_int) { *(int*)p1 […]

关于char和严格别名的通用指针

我不知道为什么下面的代码工作正常,没有gcc错误( -fstrict-aliasing -Wstrict-aliasing=1 )。 #include int main(void) { char n = 42; char *p = &n; int *q = (int *)p; *q = 10; printf(“%d|%d\n”, *p, *q); return 0; } 如果我遵循严格的别名规则: n1570,§6.5表达式 对象的存储值只能由具有以下类型之一的左值表达式访问: – 与对象的有效类型兼容的类型, – 与对象的有效类型兼容的类型的限定版本, – 对应于对象的有效类型的有符号或无符号类型, – 对应于对象有效类型的限定版本的有符号或无符号类型, – 聚合或联合类型,其成员中包含上述类型之一(包括递归地,子聚合或包含联合的成员),或者 – 一个字符类型。 但*q没有与*p兼容的类型,无论是合格版本,还是对应的有符号或无符号类型,都是字符类型。 那么,为什么允许这样做呢?

是否从size_t或uintptr_t来回转换指针会破坏严格的别名?

我建议更改一个库,其公共API目前看起来像这样: typedef size_t enh; /* handle */ int en_open(enh *handle) { struct internal *e = malloc(…); *handle = (enh)e; return 0; } int en_start(enh handle) { struct internal *e = (struct internal*)handle; return do_something(e); } 这种用法,来回于size_t破坏严格的别名吗? 为了记录,我建议在公共API中使用struct internal的典型opaque前向声明, 如此Programmers.SE关于相同代码的问题所示。

是否可以将int **和const int **替换为别名?

我的理解是这样的事情是可以的: const int ci = 42; const int *cip = &ci; int *ip = (int *)cip; int j = *ip; 那这个呢? const int ci = 42; const int *cip = &ci; const int **cipp = &cip; int **ipp = (int **)cipp; int j = **ipp;

如何在不违反严格别名规则的情况下合法地使用类型惩罚与联合在struct sockaddr的变体之间进行投射?

POSIX打算将struct sockaddr变量指针转换为可转换的,但是根据C标准的解释,这可能违反了严格的别名规则,因此违反了UB。 (请参阅下面的评论这个答案 。)我至少可以确认gcc可能至少存在问题:此代码打印Bug! 启用优化,并且Yay! 禁用优化: #include #include #include sa_family_t test(struct sockaddr *a, struct sockaddr_in *b) { a->sa_family = AF_UNSPEC; b->sin_family = AF_INET; return a->sa_family; // AF_INET please! } int main(void) { struct sockaddr addr; sa_family_t x = test(&addr, (struct sockaddr_in*)&addr); if(x == AF_INET) printf(“Yay!\n”); else if(x == AF_UNSPEC) printf(“Bug!\n”); return 0; } 在联机IDE上观察此行为。 要解决此问题, […]

C中的OO多态性,混叠问题?

我和一位同事正试图实现一个简单的多态类层次结构。 我们正在研究嵌入式系统,仅限于使用C编译器。 我们有一个基本的设计思想,在没有警告的情况下编译(-Wall -Wextra -fstrict-aliasing -pedantic),并且在gcc 4.8.1下运行正常。 但是,我们有点担心别名问题,因为我们还不完全了解何时出现问题。 为了演示我们已经编写了一个带有“接口”IHello的玩具示例和两个实现此接口“Cat”和“Dog”的类。 #include /* ——– IHello ——– */ struct IHello_; typedef struct IHello_ { void (*SayHello)(const struct IHello_* self, const char* greeting); } IHello; /* Helper function */ void SayHello(const IHello* self, const char* greeting) { self->SayHello(self, greeting); } /* ——– Cat ——– */ typedef struct Cat_ { […]

通过展开inheritance是否违反了严格的别名规则?

我有一个inheritance自struct Base的struct X. 但是,在我目前的设置中,由于对齐,X的大小为24B: typedef struct { double_t a; int8_t b; } Base; typedef struct { Base base; int8_t c; } X; 为了节省内存,我想展开Base结构,所以我创建了包含Base的字段的struct Y(以相同的顺序,总是在struct的开头),所以struct的大小是16B : typedef struct { double_t base_a; int8_t base_b; int8_t c; } Y; 然后我将在一个方法中使用struct Y的实例,该方法需要一个指向Base结构的指针: void print_base(Base* b) { printf(“%f %d\n”, b->a, b->b); } // … Y data; print_base((Base*)&data); 上面的代码是否违反了严格的别名规则,并导致未定义的行为?

Memcpy实现,严格别名

在学习c的同时,我实现了自己的memcpyfunction。 我在函数中使用了更宽泛的类型( uint32_t )。 (为简单起见,该函数仅限于4的倍数且数据正确对齐的类型) void memcpy4( void* dst , void* src , int size ) { size /= 4; for ( int i = 0 ; i < size ; i++ ) ((uint32_t*)dst)[i] = ((uint32_t*)src)[i]; } 我做了关于类型惩罚和严格别名的阅读,我相信上面的function打破了规则。 正确的实现是这样的,因为你可以使用char: void memcpy4( void* dst , void* src , int size ) { for ( int i […]

这种工会的使用是否严格符合?

鉴于代码: struct s1 {unsigned short x;}; struct s2 {unsigned short x;}; union s1s2 { struct s1 v1; struct s2 v2; }; static int read_s1x(struct s1 *p) { return p->x; } static void write_s2x(struct s2 *p, int v) { p->x=v;} int test(union s1s2 *p1, union s1s2 *p2, union s1s2 *p3) { if (read_s1x(&p1->v1)) { unsigned short […]