int data[8];
data[9] = 1;
c ++标准对此有何评论?这是未定义的行为吗?
至少C编译器(gcc -std = c99 -pedantic -W -Wall)对此没有任何说明。
感谢。
答案 0 :(得分:7)
从数组边界外部访问是未定义的行为,来自c99 draft standard部分Annex J.2
J.2未定义的行为包括以下内容:
数组下标超出范围,即使某个对象显然可以使用 给定下标(如左边的表达式a [1] [7]给出声明int a [4] [5])(6.5.6)。
和5.7
添加剂运算符段 5 中的draft C++ standard说:
当向指针添加或从指针中减去具有整数类型的表达式时,结果具有指针操作数的类型。如果指针操作数指向数组对象的元素,并且数组足够大,则结果指向与原始元素偏移的元素,以使得结果与原始元素的下标不同数组元素等于整数表达式。 [...]如果两个指针操作数和在结果指向相同的数组对象的元素,或一个过去的数组对象的最后一个元素时,评价不得产生溢出;否则,行为未定义。
为了完整起见,第5.2.1
个订阅段 1 部分说:
[...] E1 [E2]表达式(根据定义)与*((E1)+(E2))相同[注:详见5.3和5.7 *和+和8.3.4有关数组的详细信息。 - 后注]
重要的是要注意,编译器不需要为未定义的行为生成警告(诊断),1.4
实施合规性部分中的草案C ++标准段 1 说:
可诊断规则集包含本国际标准中的所有语法和语义规则,但那些包含“无需诊断”的明确表示法或描述为“未定义行为”的规则除外。 /强>
答案 1 :(得分:4)
是的,这是未定义的行为。
编译器可能会或可能不会警告您未定义的行为,即使它能够检测到它。
答案 2 :(得分:4)
这被认为是未定义的行为。如果您尝试编译将导致未定义行为的代码,则编译器不需要发出警告,尽管他们这样做很好。
希望这有帮助!
答案 3 :(得分:2)
未定义。 它可能是也可能不是无效的内存,这使它变得危险。 您可以使用像valgrind这样的工具来检测这样的错误访问。
答案 4 :(得分:2)
是的,这是未定义的行为。一切都可能发生,它可能会起作用或不起作用,它可能会工作2年然后停止工作。这是三个中最危险的:
您可以查看此内容以与其他亲戚见面: What are all the common undefined behaviour that a C++ programmer should know about?
答案 5 :(得分:2)
C和C ++不检查边界。您尝试达到的值几乎可以是任何东西。它似乎适用于您的编译器,但它不是合法的C或C ++,并且无法保证它在下次运行程序时仍然有效。
根据ISO C标准,访问bounders之外的阵列会导致
未定义的行为:行为,在使用不可移植或错误的程序结构或错误数据时,本国际标准不对其施加任何要求
当您尝试取消引用不允许程序访问的内存指针时发生分段错误,并且只是越过数组的末尾可能不会导致错误。但它最有可能会给你一些不好的价值。
答案 6 :(得分:1)
是的,它是未定义的行为,有些编译器会发出警告,有些则没有,但让我们看一下你的代码。
查看opeators []
内联实现。 a[b]
实际上是*(a + b)
。所以回到你的代码。
int data[8];
data[9] = 1;
首先,您分配堆栈的某些部分并创建指向第一个元素的指针。然后你重写一些数据,就在你的数组之后,所以你破坏了一些数据。
让我们再看一个例子:
int data[8];
int data2[8] = {};
data[9] = 1;
很可能,编译器生成的代码分配一次并创建两个指针作为数组。因此data[9] = 1;
可能会将data2
的第二个值设置为1,但不能保证这一点。