3

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)

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

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

如果结果指向数组对象的最后一个元素,则不应将其用作计算的一元运算符的操作数*

禁止评估那里的间接运算符。

问题是间接运算符是否在

*(&arr + 1) - arr

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

4

2 回答 2

4

我认为标准很清楚,*运营商在这里进行评估。评估的结果是一个永远不会转换为值的左值,但仍然使用评估的结果。

使用运算符立即获取地址时有一个特殊的例外&: in &*x, wherex有 type T *x被计算,但*and&运算符不是。T在运行时没有中间类型的左值来获取地址。所以&*x即使x是一个空指针或一个超过数组末尾的指针也是有效的。

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

于 2013-04-15T18:02:19.563 回答
0

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

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

所以数组大小为:

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

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

于 2013-04-15T18:01:50.490 回答