VisualStudio是否允许您访问数组范围之外的内容?(VS2013) 我想对VisualStudioC++的立场进行一个正式的解释,以及当您创建一个数组时,它会做什么: int a[3] = {1, 2, 3};

VisualStudio是否允许您访问数组范围之外的内容?(VS2013) 我想对VisualStudioC++的立场进行一个正式的解释,以及当您创建一个数组时,它会做什么: int a[3] = {1, 2, 3};,c++,visual-studio,compiler-errors,compiler-warnings,C++,Visual Studio,Compiler Errors,Compiler Warnings,然后你会做一些类似的事情: cout << a[4]; cout它与编译器无关,但语言的定义方式是允许的。由于内容不确定,它将导致未定义的行为 至于允许的原因,考虑下标(数组索引)操作符的定义(从ISO/IEC 1488席2011年(E)第5.2.1/1 [ExPR子]): 后缀表达式后跟方括号中的表达式是后缀表达式。其中一个表达式应具有类型“指向T”的指针,另一个表达式应具有非范围枚举或整数类型。结果是类型为“T”的左值。类型“T”应为完全定义的对象类型。表达式E1[E2]与*(

然后你会做一些类似的事情:

cout << a[4];

cout它与编译器无关,但语言的定义方式是允许的。由于内容不确定,它将导致未定义的行为

至于允许的原因,考虑下标(数组索引)操作符的定义(从ISO/IEC 1488席2011年(E)第5.2.1/1 [ExPR子]):

后缀表达式后跟方括号中的表达式是后缀表达式。其中一个表达式应具有类型“指向
T
”的指针,另一个表达式应具有非范围枚举或整数类型。结果是类型为“
T
”的左值。类型“
T
”应为完全定义的对象类型。表达式
E1[E2]
*((E1)+(E2))

[我的重点]


由于上述原因,将数组
E1
衰减为指向第一个元素的指针(即,它相当于
&(E1)[0]
),然后编译器使用
(E1)+(E2)
执行指针算术。由于数组已衰减为指针,因此不可能进行边界检查。

它与编译器无关,但语言是以允许的方式定义的。由于内容不确定,它将导致未定义的行为

至于允许的原因,考虑下标(数组索引)操作符的定义(从ISO/IEC 1488席2011年(E)第5.2.1/1 [ExPR子]):

后缀表达式后跟方括号中的表达式是后缀表达式。其中一个表达式应具有类型“指向
T
”的指针,另一个表达式应具有非范围枚举或整数类型。结果是类型为“
T
”的左值。类型“
T
”应为完全定义的对象类型。表达式
E1[E2]
*((E1)+(E2))

[我的重点]


由于上述原因,将数组
E1
衰减为指向第一个元素的指针(即,它相当于
&(E1)[0]
),然后编译器使用
(E1)+(E2)
执行指针算术。由于数组已衰减为指针,因此不可能进行边界检查。

为什么要使用javascript标记?@NinaScholz,因为我在评论中提到了javascript。不知道你是否看到了。我在想,也许我也会得到一个javaScript解释。不管怎样,我删除了标签,因为zeromus要求我这么做。哲学是不为你不用的东西付钱。这就是说,不要将边界检查的成本强加给开发者——而是假设开发者已经进行了这样的检查,如果他认为他需要的话。这种检查包含在标准库结构(如std::array和std::vector)中,或者可以配置为在调试或发布版本中使用它们。在javascript中,对于未初始化的索引,您只会得到一个
未定义的
。为什么要使用javascript标记?@NinaScholz,因为我在注释中提到了javascript。不知道你是否看到了。我在想,也许我也会得到一个javaScript解释。不管怎样,我删除了标签,因为zeromus要求我这么做。哲学是不为你不用的东西付钱。这就是说,不要将边界检查的成本强加给开发者——而是假设开发者已经进行了这样的检查,如果他认为他需要的话。这种检查包含在标准库结构(如std::array和std::vector)中,或者可以配置为在调试或发布版本中使用它们。在javascript中,对于未初始化的索引,只需
未定义的