访问多维数组的元素是否越界未定义行为?
Is accessing an element of a multidimensional array out of bounds undefined behavior?
请原谅这个令人困惑的问题标题,但我不确定如何更清楚地表达它。
在 C 中,越界访问数组被归类为未定义行为。但是,数组元素保证在内存中连续布局,数组下标运算符是指针运算的语法糖(例如 x[3] == *(x + 3)
)。因此,我个人希望下面代码的行为是 well-defined:
int array[10][10];
int i = array[0][15]; // i == array[1][5]?
如果我对标准的解释是正确的,这将是未定义的行为。我错了吗?
根据标准,这显然是未定义的行为,因为这种情况在 J.2 undefined behaviour 部分中明确列出(在在线 C99 标准草案中找到):
An array subscript is out of range, even if an object is apparently
accessible with the given subscript (as in the lvalue expression
a[1][7]
given the declaration int a[4][5]
) (6.5.6).
你的例子仍然可以工作,实际上我在C代码中看到了很多这样的情况;不过准确的说是UB
标准明确指出,给定 unsigned char arr[10][10];
,如果 x
超过 9,则尝试访问 arr[0][x]
将产生 UB。
然而,我认为同样清楚的是,该标准的作者打算允许代码将任何对象(包括多维数组)的地址作为字符指针,然后将该指针索引到访问对象的所有字节。
如果标准说 arr[0]
产生一个 char*
类型的指针,它只能用于访问前十个元素,但是 (char*)arr
会产生一个指针可以访问整个数组,可以满足上述两个目标,但我在标准中看不到任何暗示 arr[0]
和 (char*)arr
不等同的内容。
最有可能的是,该标准的作者期望无论标准是否完整描述了这些极端情况,实现都会寻求明智的行为。对于这个特定问题,我不确定 clang 和 gcc 是否符合这样的期望,但这样的期望通常并不成立。
请原谅这个令人困惑的问题标题,但我不确定如何更清楚地表达它。
在 C 中,越界访问数组被归类为未定义行为。但是,数组元素保证在内存中连续布局,数组下标运算符是指针运算的语法糖(例如 x[3] == *(x + 3)
)。因此,我个人希望下面代码的行为是 well-defined:
int array[10][10];
int i = array[0][15]; // i == array[1][5]?
如果我对标准的解释是正确的,这将是未定义的行为。我错了吗?
根据标准,这显然是未定义的行为,因为这种情况在 J.2 undefined behaviour 部分中明确列出(在在线 C99 标准草案中找到):
An array subscript is out of range, even if an object is apparently accessible with the given subscript (as in the lvalue expression
a[1][7]
given the declarationint a[4][5]
) (6.5.6).
你的例子仍然可以工作,实际上我在C代码中看到了很多这样的情况;不过准确的说是UB
标准明确指出,给定 unsigned char arr[10][10];
,如果 x
超过 9,则尝试访问 arr[0][x]
将产生 UB。
然而,我认为同样清楚的是,该标准的作者打算允许代码将任何对象(包括多维数组)的地址作为字符指针,然后将该指针索引到访问对象的所有字节。
如果标准说 arr[0]
产生一个 char*
类型的指针,它只能用于访问前十个元素,但是 (char*)arr
会产生一个指针可以访问整个数组,可以满足上述两个目标,但我在标准中看不到任何暗示 arr[0]
和 (char*)arr
不等同的内容。
最有可能的是,该标准的作者期望无论标准是否完整描述了这些极端情况,实现都会寻求明智的行为。对于这个特定问题,我不确定 clang 和 gcc 是否符合这样的期望,但这样的期望通常并不成立。