将char * 转换为void**

af7jpaap  于 2023-10-16  发布在  其他
关注(0)|答案(1)|浏览(103)

假设我有:

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++在这方面是相似的,但也许我错了。

6jjcrrmo

6jjcrrmo1#

我知道char * 可以别名任何东西,但是这种津贴是不是相反的?

TLDR:

不可以。您不能将[un[signed]] char数据视为任何其他类型而不违反严格别名。
但是,untyped 内存是不同的。你可以通过赋值把非类型化的内存当作一种新的类型。

完整答案:

给定char *bufptr,转换为void **

(void **)bufPtr

可能违反6.3.2.3指针第7段:
指向对象类型的指针可以被转换为指向不同对象类型的指针。如果结果指针与引用的类型没有正确对齐,则行为未定义。
请注意,指针不必被解引用来调用未定义的行为-仅仅 * 创建 * 一个未对齐的指针就足以调用未定义的行为。
将该值转换为取消引用的指针,

*(void **)bufPtr = ptr1;

可能会也可能不会违反严格的别名,这取决于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。

相关问题