【问题标题】:Does the array-to-pointer conversion annihilate the evaluation of the indirection operator?数组到指针的转换是否会取消对间接运算符的评估?
【发布时间】:2013-04-15 17:47:52
【问题描述】:

Find size of array without using sizeof 中,数组的大小是通过

int arr[100];
printf ("%td", (&arr)[1] - arr);

现在,出于指针算术的目的,arr 被认为是单元素数组的元素,所以

&arr + 1

是该(概念)单元素数组末尾的指针,因此当减去arr[0]的地址时,得到arr中的元素数。

(&arr)[1]中,该指针是间接运算符的操作数,

(&arr)[1] ≡ *(&arr + 1)

然后根据 6.3.2.1 (3) 将生成的数组表达式转换为 int*

到目前为止,一切都很好。但是6.5.6(8)最后一句(加法运算符),

如果结果指向数组对象的最后一个元素,它 不得用作被评估的一元 * 运算符的操作数。

禁止在此处评估间接运算符。

问题是间接运算符是否在中求值

*(&arr + 1) - arr

(在这种情况下,该表达式将调用未定义的行为)或数组到指针的转换会取消评估(在这种情况下一切都很好),例如获取地址 (&(*(&arr + 1))) 或对其应用 sizeof会..

【问题讨论】:

  • 我知道你在问 C,但是 FWIW,在 C++ 中,这个想法(尚未在标准中正确表达)是行为未定义的左值到右值转换.由于这不会发生,因此此代码将是有效的。
  • *(&arr + 1) 是未定义的行为,(&arr)[1] 也是如此。我不确定我是否理解您的问题。
  • @ouah 但是取地址或者申请sizeof会导致*不被评估,那么就没有问题了。问题是数组到指针的转换是否有同样的效果。

标签: c arrays pointers language-lawyer


【解决方案1】:

我认为标准非常明确,* 运算符在此处进行评估。求值的结果是一个左值,它永远不会被转换成一个值,但仍然会使用求值的结果。

使用& 运算符立即获取地址时有一个特殊例外:在&*x 中,其中x 的类型为T *x 被求值,但* 和@987654329 @ 运算符不是。在运行时没有T 类型的中间左值,其地址被取走。所以&*x 是有效的,即使x 是一个空指针或一个超过数组末尾的指针。

由于您没有使用& 运算符来获取地址,因此该例外不适用。数组到指针的转换没有类似的异常,所以即使x是数组类型,如果x实际上没有指向任何对象,*x也是无效的。

【讨论】:

  • 我也倾向于这样认为,但正如Alexey Frunze's answer 下的 cmets 所示,我们不太确定标准的解释。数组到指针的转换是否需要对数组类型的表达式求值?
  • @DanielFischer 据我所知,在这些 cmets 中,没有任何论据支持标准当前允许这样做的想法,唯一的疑问是标准是否应该 允许它(这是否是标准中的缺陷)。我错过了什么吗? FWIW,无论标准怎么说,如果它在 C 的任何当前或未来实现中中断,我都会感到非常惊讶。
  • 重新检查线程后,我认为您没有遗漏任何内容。 (而且我认为如果它在实践中没有按预期工作,每个人都会感到非常惊讶。)
  • 您能否以某种方式改写或扩展答案?我已经读过很多遍了,但我仍然不确定这是否意味着应该有 UB 或者意味着不应该。
  • @AlexeyFrunze 根据标准目前所说的,行为是未定义的。我的编辑是否有助于清除它?
【解决方案2】:

你想这样做:对于 any T x;,确实&x + 1 是刚刚超过x 末尾的地址,并且在数字上它是一个获得的指针通过将&x 增加sizeof(T)(所以sizeof 仍然存在!)。

现在如果T = U[N],则xN 类型为U 的元素的数组。但是指向这样一个数组的指针也是指向这样一个数组的第一个元素的指针。所以我们可以将&x(这是一个(T*)[N])重新解释为U*,我们可以对&x + 1做同样的事情。但是现在这些指针是U* 类型的,所以它们的区别在于元素的数量。

所以数组大小为:

(U*)(&x + 1) - (U*)(&x)

请注意,由于数组到指针的衰减,(U*)(&x) 实际上与 x 的衰减是同一个指针。

【讨论】:

  • 是的,确实如此,但问题是实际使用的表达式是否定义明确或导致UB。
猜你喜欢
  • 2012-07-24
  • 1970-01-01
  • 2017-06-19
  • 2012-02-01
  • 2014-11-07
  • 2015-01-23
  • 2021-01-14
  • 1970-01-01
  • 2023-04-10
相关资源
最近更新 更多