【发布时间】:2021-02-14 09:20:16
【问题描述】:
我知道 C 标准承诺指向任何对象的指针可以往返于 void * 并返回。换句话说,
T obj;
assert(&obj == (T *) (void *) &obj);
现在,我想知道指针算法。它是如何遵循的/它在哪里说的
T *arr[2] = {0};
assert(arr[1] == (T *) (((void **)arr)[1]))
有效吗?这还能保证吗?
我有一种预感,答案是“不能保证”,甚至是“这是 UB”。原因是,据我“所知”,void * 的表示不必等于其他指针的表示。例如,如果 void 指针的大小比其他指针大,void ** 上的指针运算可能无法工作。所以除非上述是合法的,我想知道如果我想用泛型代码对指针数组进行操作,我应该在实践中做什么。
【问题讨论】:
-
C 标准中没有任何内容可以保证这将起作用。正如您所注意到的,没有任何东西可以保证
void *和T *具有相同的表示或大小。但是,即使他们这样做了,使用void *类型的左值访问数组的元素T *也违反了 C 2018 6.5 7 中的别名规则。该行为未由标准定义,因此assert不能保证失败,即使在某种意义上,左右操作数具有相同的值。 -
这个话题是discussed here。它回答了你的问题吗?
-
如果您知道您的程序将在 C 实现中执行,其中使用的指针类型具有相同的大小和表示形式,那么使用指针的定义方法是使用
unsigned char *指针从数组中取出字节,将字节复制到void *,然后使用强制转换将void *转换为所需的类型。
标签: c