访问超出C和C ++限制的数组

int data[8]; data[9] = 1; 

c ++标准对此有何评论? 这是未定义的行为吗?

至少C编译器(gcc -std = c99 -pedantic -W -Wall)对此没有任何说明。

谢谢。

访问数组边界外部是未定义的行为,来自c99草案标准部分Annex J.2 J.2未定义的行为包括以下几点:

数组下标超出范围,即使一个对象显然可以使用给定的下标访问(如左边的表达式[1] [7],给出声明int a [4] [5])(6.5.6)。

5.7添加剂操作符5节中的C ++标准草案说:

当一个具有整数类型的表达式被添加到指针或从指针中减去时,结果具有指针操作数的类型。 如果指针操作数指向数组对象的元素,并且数组足够大 ,则结果指向与原始元素偏移的元素,使得结果元素和原始数组元素的下标的差异等于整数表达式。 […]如果指针操作数和结果都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,则评估不应产生溢出; 否则,行为未定义。

为完整起见,第5.2.1订阅1段说:

[……]表达式E1 [E2]与*((E1)+(E2))相同 [注意:有关数组的详细信息请参阅5.3和5.7以及*和+和8.3.4的详细信息。 – 尾注]

值得注意的是,编译器不需要为未定义的行为生成警告( 诊断 ), 1.4 实施合规性1节中的草案C ++标准说:

可诊断规则集包含本国际标准中的所有语法和语义规则, 除了那些包含“不需要诊断”或被描述为导致“未定义行为”的显式符号的规则。

是的,它是未定义的行为。

编译器可能会或可能不会警告您未定义的行为,即使它能够检测到它。

这被认为是未定义的行为。 如果您尝试编译将导致未定义行为的代码,则编译器不需要发出警告,尽管他们这样做很好。

希望这可以帮助!

未定义。 它可能是也可能不是无效的内存,这使它变得危险。 您可以使用像valgrind这样的工具来检测这样的错误访问。

是的,它是未定义的行为。 一切都可能发生,它可能起作用或不起作用,它可能会工作2年然后停止工作。 这是三个中最危险的:

  • 未定义的行为
  • 未指明的行为
  • 实现定义的行为

你可以检查这个以满足其他亲戚: C ++程序员应该知道的所有常见的未定义行为是什么?

未定义,未指定和实现定义的行为

C和C ++不检查边界。 您尝试达到的值几乎可以是任何东西。 它似乎适用于您的编译器,但它不是合法的C或C ++,并且无法保证它在下次运行程序时仍然可用。

根据ISO C标准,访问bounders外的arrays会导致

未定义的行为:使用不可移植或错误的程序结构或错误数据时的行为,本国际标准不对此要求

当您尝试取消引用不允许程序访问的内存指针时,就会出现分段错误,只是越过数组的末尾可能不会导致错误。 但它最有可能给你一些不好的价值。

是的,它是未定义的行为,一些编译器会发出警告,其他人则没有,但让我们看看,你的代码是这样做的。

看看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,但是不能保证这一点。