问题描述
在另一个问题中,我看到了&studmark[STUDNO][0]
,其中STUDNO
是数组的大小.
In another question I saw &studmark[STUDNO][0]
where STUDNO
is the size of the array.
我现在想知道该代码是否已经是未定义的行为. studmark[STUDNO]
是最后一种,尽管可能会创建它,但不能对其进行访问.用[0]
编制索引以形成地址有效吗?还是必须只使用studmark[STUDNO]
,然后降级为指针的最后一个指针?
I wonder now if that code is already undefined behaviour. studmark[STUDNO]
is one-past-the-end and while it may be created it must not be accessed. Is indexing that with [0]
to then form the address valid? Or must one use simply studmark[STUDNO]
which then degrades to a pointer one-past-the-end?
请以任何一种方式引用该标准.
Arguments either way please with references to the standard.
更新:示例代码和输出
#include <stdio.h>
#define STUDNO 16
int studmark[STUDNO][2];
int main() {
printf("&studmark = %p\n", studmark);
printf("&studmark[1][0] = %p\n", &studmark[1][0]);
printf("&studmark[STUDNO-1][0] = %p\n", &studmark[STUDNO-1][0]);
printf("&studmark[STUDNO][0] = %p\n", &studmark[STUDNO][0]);
return 0;
}
编译没有警告和输出:
./foo
&studmark = 0x601060
&studmark[1][0] = 0x601068
&studmark[STUDNO-1][0] = 0x6010d8
&studmark[STUDNO][0] = 0x6010e0
推荐答案
鉴于studmark
的定义如下:
int studmark[STUDNO][2];
然后表达式&studmark[STUDNO][0]
调用未定义的行为.
为使指针取消引用更加明显,首先,我们将从数组索引表示形式切换为指针表示形式. C11标准的6.5.2.1p2节规定:
To make the pointer dereferences more apparent, first we'll switch from array index notation from pointer notation. Section 6.5.2.1p2 of the C11 standard states:
因此上面的表达式变为:
So the above expression becomes:
&*(studmark[STUDNO] + 0)
哪个会成为:
&*(*(studmark + STUDNO) + 0)
此表达式以&
和*
运算符开头.当&
优先于*
时,它们彼此抵消.这在6.5.3.2p3节中有详细说明:
This expression starts with the &
and *
operators. When &
preceedes *
they cancel each other out. This spelled out in section 6.5.3.2p3:
因此可以简化为:
*(studmark + STUDNO) + 0
现在,我们来看一下添加项.这是有效的,因为根据6.5.6p8节,创建指向数组末尾一个元素的指针是合法的:
Now we look at the addition. This is valid because creating a pointer to one element past the end of the array is legal as per section 6.5.6p8:
这意味着studmark + STUDNO
是有效的指针,但不能取消引用.这就是问题所在.*(studmark + STUDNO)
调用未定义的行为,因为它取消了对数组末尾的一个元素的引用.
This means studmark + STUDNO
is a valid pointer, but it cannot be dereferenced. This is where the problem comes in. *(studmark + STUDNO)
invokes undefined behavior because it dereferences one element past the end of the array.
所以&studmark[STUDNO][0]
是未定义的行为.
相反,这是有效的:
&studmark[STUDNO]
等于:
&*(studmark + STUDNO)
随后:
studmark + STUDNO
因为它创建了指向数组末尾一个元素的指针,但没有取消引用它.
Because it creates a pointer to one element past the end of an array but does not dereference it.
这篇关于是否合法或越界形成了末尾第一个元素的地址?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!