求教c++指针数组越界没有异常提示
求教c++指针数组越界没有错误提示
例如:int **array;//假定array是10*10大小吧
array[1][9],然后在一个循环里array[1][9]增长到array[1][11],竟然没有出错。
有知道原因的吗?麻烦解释一下,谢谢
------解决方案--------------------
因为无所谓界的存在,指针而已
------解决方案--------------------
指针是可以越界的,这个需要你自己检测范围
------解决方案--------------------
int **array;这个是二维数组指针。
int array[10][10];这个才是二维数组。
-
数组越界并不算是错误。
只是会导致未知的行为而已。
------解决方案--------------------
我要是编译器,也不知道int **array的边界在哪儿呀?
我发现VC6.0对这种代码也没有编译报错:
int ar[10];
ar[10] = 1;
还是要靠自己检查边界啊。
------解决方案--------------------
------解决方案--------------------
要看当时操作系统的存储管理情况了,如果读写到无效的线性地址是要core掉的,如果线性地址对当前应用程序有效,那可能就读取到无意义的数据或者覆盖到有效的数据,这就是C组语言不安全的地方了~
------解决方案--------------------
因为机器本身就是这样的。而C语言贴近底层,没有访问检查。
------解决方案--------------------
1.如果是array声明的是二维数组,数组里面元素的内存都是连续分配的,a[1][11]相当于是访问到了从第一行超出了两个元素的地方,也就是访问到了a[2][1],注(a[1][9],a[2][0],a[2][1]这三个元素的内存是连续的)
2.如果array不是二维数组,而是指针数组,则访问的a[1][11]明显越界了,但是不确定访问到了什么东东。
例如
3.C++在使用指针的时候是不会自动进行数组越界检查的,因为在C++眼里,越界的数组依然是合法的内存地址。
例如:int **array;//假定array是10*10大小吧
array[1][9],然后在一个循环里array[1][9]增长到array[1][11],竟然没有出错。
有知道原因的吗?麻烦解释一下,谢谢
------解决方案--------------------
因为无所谓界的存在,指针而已
------解决方案--------------------
指针是可以越界的,这个需要你自己检测范围
------解决方案--------------------
int **array;这个是二维数组指针。
int array[10][10];这个才是二维数组。
-
数组越界并不算是错误。
只是会导致未知的行为而已。
------解决方案--------------------
我要是编译器,也不知道int **array的边界在哪儿呀?
我发现VC6.0对这种代码也没有编译报错:
int ar[10];
ar[10] = 1;
还是要靠自己检查边界啊。
------解决方案--------------------
------解决方案--------------------
要看当时操作系统的存储管理情况了,如果读写到无效的线性地址是要core掉的,如果线性地址对当前应用程序有效,那可能就读取到无意义的数据或者覆盖到有效的数据,这就是C组语言不安全的地方了~
------解决方案--------------------
因为机器本身就是这样的。而C语言贴近底层,没有访问检查。
------解决方案--------------------
1.如果是array声明的是二维数组,数组里面元素的内存都是连续分配的,a[1][11]相当于是访问到了从第一行超出了两个元素的地方,也就是访问到了a[2][1],注(a[1][9],a[2][0],a[2][1]这三个元素的内存是连续的)
2.如果array不是二维数组,而是指针数组,则访问的a[1][11]明显越界了,但是不确定访问到了什么东东。
例如
3.C++在使用指针的时候是不会自动进行数组越界检查的,因为在C++眼里,越界的数组依然是合法的内存地址。
- C/C++ code
#include <iostream> using namespace std; void InitArray(int *p, int start, size_t count) { for ( size_t i = 0; i < count; ++i) { p[i] = start+i; } } void printArray(int *p, size_t count) { for ( size_t i = 0; i < count; ++i) { cout<<p[i]<<", "; } cout<<endl; } int main() { int pArray[10][10]; for ( size_t i = 0; i < 10; ++i ) { InitArray(pArray[i], i*10, 10); //初始化每行的数组为0,1,2,……。第二行为10,11,12……以此类推 printArray(pArray[i], 10); // } int addr = (int)&pArray[1][11]; //分别取两个元素的地址 int addr1 = (int)&pArray[2][1]; if ( addr == addr1 ) { //证明两个元素指向的内存是同一个 } int **qArray = new int *[10]; for ( size_t j= 0; j < 10; ++j ) { qArray[j] = new int[10]; InitArray(pArray[j], j*10, 10); //随便初始化 printArray(pArray[j], 10); // } int addr2 = (int)&qArray[1][11]; //分别取两个元素的地址 int addr3 = (int)&qArray[2][1]; if ( addr2 == addr3 ) { //证明两个元素指向的内存是同一个 } return 0; }
------解决方案--------------------
VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
想要从本质上理解C指针,必须学习汇编以及C和汇编的对应关系。
从汇编的角度理解和学习C语言的指针,原本看似复杂的东西就会变得非常简单!
指针即地址。“地址又是啥?”“只能从汇编语言和计算机组成原理的角度去解释了。”
提醒:
“学习用汇编语言写程序”
和
“VC调试(TC或BC用TD调试)时按Alt+8、Alt+6和Alt+5,打开汇编窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应内存和寄存器变化,这样过一遍不就啥都明白了吗。
(Linux或Unix下可以在用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。)
想要从本质上理解C指针,必须学习C和汇编的对应关系。”
不是一回事!
不要迷信书、考题、老师、回帖;
要迷信CPU、编译器、调试器、运行结果。
并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。
任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实!
不要写连自己也预测不了结果的代码!
- C/C++ code
//在堆中开辟一个4×5的二维int数组 #include <stdio.h> #include <malloc.h> int **p; int i,j; void main() { p=(int **)malloc(4*sizeof(int *)); if (NULL==p) return; for (i=0;i<4;i++) { p[i]=(int *)malloc(5*sizeof(int)); if (NULL==p[i]) return; } for (i=0;i<4;i++) { for (j=0;j<5;j++) { p[i][j]=i*5+j; } } for (i=0;i<4;i++) { for (j=0;j<5;j++) { printf(" %2d",p[i][j]); } printf("\n"); } for (i=0;i<4;i++) { free(p[i]); } free(p); } // 0 1 2 3 4 // 5 6 7 8 9 // 10 11 12 13 14 // 15 16 17 18 19