数组到指针的转换是否会消除对间接运算符的评估?

时间:2013-04-15 17:47:53

标签: c arrays pointers language-lawyer

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)))或应用{{1它会... ..

2 个答案:

答案 0 :(得分:4)

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

使用&运算符立即执行地址时有一个特殊例外:在&*xx的类型为T *x为已评估,但*&运算符不是。在运行时没有类型T的中间左值,其中包含地址。因此&*x即使x为空指针或超出数组末尾也是有效的。

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

答案 1 :(得分:0)

您希望这样做:对于任何 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的衰减指针相同。