我正在定义一个大小为9的数组。但是当我访问数组索引10时,它没有给出任何错误。
int main() {
bool* isSeedPos = new bool[9];
isSeedPos[10] = true;
}
我希望得到编译器错误,因为我的数组中没有数组元素isSeedPos[10]
。
为什么我没有收到错误?
答案 0 :(得分:5)
这不是问题。
C ++数组中没有绑定检查。您可以访问超出数组限制的元素(但这通常会导致错误)。
如果你想使用一个数组,你必须自己检查你是不是在界外(你可以将sizee保存在一个单独的变量中,就像你所做的那样)。
当然,更好的解决方案是使用标准库容器,例如std::vector
。
使用std::vector
,您可以
myVector.at(i)
方法获取第i个元素(如果超出界限则会抛出异常)myVector[i]
,但您必须自己进行边界检查(例如在访问之前尝试if (i < myVector.size()) ...
)另请注意,在您的情况下,std::vector<bool>
是一个专门版本,因此每个bool
只占用一位内存(因此它使用的内存少于bool
数组,可能是也可能不是你想要的东西。
答案 1 :(得分:1)
不,编译器不需要为此情况发出诊断信息。编译器不会为您执行边界检查。
您有责任确保不要编写这样的损坏代码,因为编译器不会错误。
答案 2 :(得分:1)
与java和python等其他语言不同,数组访问不受C或C ++的绑定检查。这使得访问数组更快。您有责任确保自己保持在一定范围内。
但是,在这种简单的情况下,一些编译器可以在编译时检测错误。
此外,某些工具(如valgrind)可以帮助您在运行时检测此类错误。
答案 3 :(得分:1)
您使用的编译器/调试器是什么? MSVC ++会抱怨它并告诉你你写出了一个数组的界限。 但是标准并不要求这样做。 它可能随时崩溃,导致未定义的行为。
答案 4 :(得分:1)
原始数组不进行边界检查。如果你想要边界检查,你应该使用std :: vector。在数组结束后你正在访问无效的内存,纯粹是运气好了。
答案 5 :(得分:1)
使用std :: vector代替。一些实现将在调试模式下进行边界检查。
答案 6 :(得分:1)
没有规则声明在c中检查内存访问,简单明了。当你要求一个bool数组时,操作系统可能会更快地为你提供一个16位的32位数组,而不是9位数组。这意味着你甚至可能不会写作或阅读别人的空间。
C ++很快,而且速度快的原因之一就是因为很少检查你正在做什么,如果你要求一些内存,那么编程语言就会假设你知道你在做什么,如果操作系统没有抱怨,那么一切都会运行。
答案 7 :(得分:1)
您所提供的索引没有运行时检查,访问元素10不正确但可能。有两件事可能发生:
答案 8 :(得分:0)
没有问题!您只是访问不应访问的内存。您可以在阵列之后访问内存。
答案 9 :(得分:0)
这不是Java。在C或C ++中没有边界检查;你可以写给那个索引真是太幸运了。
答案 10 :(得分:0)
isSeedPos
不知道数组有多大。它只是指向内存中位置的指针。当您指向isSeepPos[10]
时,行为未定义。机会迟早会导致段错误,但不要求崩溃,并且肯定没有标准的错误检查。
答案 11 :(得分:0)
写这个位置很危险。
但是编译器会让你这样做 - 实际上你正在写一个超过分配给该数组的内存的最后一个字节=不是一件好事。
C ++与许多其他语言不太相似 - 它假设您知道自己在做什么!
答案 12 :(得分:0)
C和C ++都允许您写入任意内存区域。这是因为它们最初源自(并且仍然用于)低级编程,您可能合法地想要写入内存映射外设或类似内容,并且因为当程序员已经知道值时省略边界检查更有效将在(例如,对于数组中的0到N的循环,他/她知道0和N在边界内,因此检查每个中间值是多余的)。
然而,事实上,现在你很少想这样做。如果你使用arr [i]语法,你基本上总是想写入在arr中声明的数组,而不是做任何其他事情。但如果你愿意,你还可以。
如果您执行写入任意内存(就像在这种情况下那样),它将成为您程序的一部分,并且它会在您不知情的情况下更改其他一些关键数据(现在,或者稍后当你对代码进行更改并忘记你正在做的事情时;或者它将写入未分配给程序的内存,操作系统将关闭它以防止出现更严重的问题。
如今: