假设我有:
char * bufPtr = ...; // points into a char array with at least sizeof(void *) chars remaining
void *ptr1 = ...;
void *ptr2;
假设bufPtr
正确对齐,则
*(void **)bufPtr = ptr1; // (1)
ptr2 = *(void **)bufPtr; // (2)
法律的?我知道char *
可以别名任何东西,但这种允许是另一个方向吗?
**更新:**我正在使用的代码库是C语言,所以这是我最感兴趣的语言(如果我只能得到一个答案)。我认为C和C++在这方面是相似的,但也许我错了。
1条答案
按热度按时间6jjcrrmo1#
我知道char * 可以别名任何东西,但是这种津贴是不是相反的?
TLDR:
不可以。您不能将
[un[signed]] char
数据视为任何其他类型而不违反严格别名。但是,untyped 内存是不同的。你可以通过赋值把非类型化的内存当作一种新的类型。
完整答案:
给定
char *bufptr
,转换为void **
,可能违反6.3.2.3指针第7段:
指向对象类型的指针可以被转换为指向不同对象类型的指针。如果结果指针与引用的类型没有正确对齐,则行为未定义。
请注意,指针不必被解引用来调用未定义的行为-仅仅 * 创建 * 一个未对齐的指针就足以调用未定义的行为。
将该值转换为取消引用的指针,
可能会也可能不会违反严格的别名,这取决于
bufptr
实际指向的是什么。从评论转移到聊天,记忆已经被定性为“非类型化”。在这种情况下,这样的赋值并不违反严格别名。
然而,该内存的使用历史可能会影响该内存是否保持非类型化。请参见Does C strict aliasing make untyped static memory pools impossible?。特别注意this answer:
这样的分配器在 * 严格符合 * C中是无法实现的,C是不依赖于未指定、未定义或实现定义的行为(并且不超过任何最小实现限制)的C代码。完全有可能在 conforming C中编写这样的分配器,这是具有扩展的C。
如果使用GCC,我将使用
-fno-strict-aliasing
和-fno-ipa-strict-aliasing
编译分配器代码,如果不使用GCC,则使用等效代码。参见https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-fstrict-aliasing。