是否合法或越界形成了末尾第一个元素的地址

是否合法或越界形成了末尾第一个元素的地址

本文介绍了是否合法或越界形成了末尾第一个元素的地址?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在另一个问题中,我看到了&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.

这篇关于是否合法或越界形成了末尾第一个元素的地址?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-01 10:26