请原谅令人困惑的问题标题,但我不确定如何更清楚地表达它。
在C中,超出范围访问数组被归类为未定义行为。但是,保证数组元素在内存中连续放置,并且数组下标运算符是指针算术的语法糖(例如x[3] == *(x + 3)
)。因此,我个人希望以下代码的行为得到明确定义:
int array[10][10];
int i = array[0][15]; // i == array[1][5]?
如果我对标准的解释正确,那将是未定义的行为。我错了吗?
根据标准,显然是未定义的行为,因为这种情况在J.2 undefined behaviour节中找到(在在线C99标准草案中找到):
数组下标超出范围,即使对象显然是 可使用给定的下标访问(如左值表达式
a[1][7]
给出了声明int a[4][5]
)(6.5.6)。
您的示例仍然可以工作,实际上我已经在C代码中看到了很多这样的情况;但是,准确地说是UB。
标准非常清楚,给定unsigned char arr[10][10];
,如果arr[0][x]
超过9,则尝试访问x
会产生UB。
但是,我认为同样很清楚,该标准的作者打算允许代码将任何对象的地址(包括多维数组)作为字符指针,然后对该指针进行索引以访问所有对象的字节数。
[如果标准说arr[0]
产生类型为char*
的指针,该指针只能用于访问前十个元素,但是(char*)arr
会产生可以访问整个数组的指针,那将可以满足上述两个目标,但我在标准中看不到任何暗示arr[0]
和(char*)arr
彼此不相等的提示。
[标准作者极有可能期望实现在这种极端情况下寻求合理的表现,无论标准是否对其进行了充分描述。对于该特定问题,我不确定clang和gcc是否符合此类期望,但总体而言,此类期望并不成立。