C语言中数组越界的例子
2015-07-26 10:33
302 查看
前几天在论坛闲逛,偶然发现了一个帖子,说的是数组输出的问题,
学习了,后面经过自己的查找,发现确实有这个情况。主要是因为初学者对于数组的定义还不清楚,数组的第一个位置应该是0开始的,但是往往会从自己的习惯来定义数组的使用,所以就造成“奇怪”结果。
比如下面的这个例子
#define num 10
int a[num];
我们都知道 使用的时候只有 a[0] 到 a[9] 这10个变量;
同时也知道使用a[10]属于数组越界,平时应该避免这么用;
......
但是, a[10]的值到底是多少?a[10] = 10;
当然 a[11],a[12]等等都是毫无意义的了;
经测试 num = 10, 100, 1000...时,
a[10] = 10; a[100] = 100; a[1000] = 1000;...
求详细解答~ a[num] = num;
关键问题是可否将该语句应用到实际编程中去?
我觉得大伙曲解了我的意思,个人觉得这个应该和数组声明,以及堆栈有关,能否从这个角度给个解答?
另外10,100,1000指的是修改 #define num 10 这个宏~~!
内存给num分配的存储位置紧跟数组a后面,在printf(“%d”, a【num】)时输出了数组a后面地址上的内容,即num的值,该值只读不可修改
追问:
的确,根据不同的环境,改值是会随机发生变化,和我猜想的一样,越界只是访问到了a[num]的这个num所在的位置,才造成的这一结果;谢谢大伙了,但是只能有一个最佳;
追答:
我也用gcc编译器,打印的a【num】是num的值,这一假设的确成立
只是不知道是否可以当成一个惯例来使用
提问者评价
C语言漏洞多多,但是我们得知其所以然!!!
又比如下面这个精心的例子。
大家都知道,在C语言中一般是不会检查数组的下标范围的,这样的好处是给了程序员很大的灵活性,更宜于写出高效的代码。如果定义一个数组a
,其有效下标范围为0 - (n-1),但你要引用下标n,编译器一般是不提示错误的,但是这样也潜在的隐含着一些隐患。
请看如下语句:(32位机器上)
#include <stdio.h>
int main(void)
{
int i;
int a[3] = {1, 2, 3};
for (i = 1; i <= 3; i++)
{
a[i] = 0;
}
return(0);
}
现在我们假设计算机分配给变量i内存位置为0022FF5C
数组a中各元素所分配的内存位置如下:
a[0]地址:0022FF50
a[1]地址:0022FF54
a[2]地址:0022FF58
请看for()循环:
i = 1时,把a[1]置0。i自加一次变为2,把a[2]置0。i再自加变为3。
注意了!!!
当i变为3时,程序将找到数组元素a[3]所在的内存位置(即本例中分配给变量i的内存单元0022FF5C),并写入0,从而导致变量i值为0。接着到for()循环中去判断条件 i <= 3,因为i的值刚才被置为0,i <= 3成立,导致再次开始执行循环。
就后程序将陷入死循环。
这就是C中数组不检查下标的一些隐患。但是现在众多的编译器已经对此缺陷做了设计上改良和优化。
平时写一些有关数组的程序时,对数组的元素个数,最好是采取宏定义的方式,比如#define N 10,或是先把元素个数留空(留空时要记得一定要初始化哦),在用到数组元素个数的时候用sizeof方法计算一下就可以了。比如本例子中可以用sizeof(a)/sizeof(a[0])来计算出数组中所包含的元素的个数。
学习了,后面经过自己的查找,发现确实有这个情况。主要是因为初学者对于数组的定义还不清楚,数组的第一个位置应该是0开始的,但是往往会从自己的习惯来定义数组的使用,所以就造成“奇怪”结果。
比如下面的这个例子
#define num 10
int a[num];
我们都知道 使用的时候只有 a[0] 到 a[9] 这10个变量;
同时也知道使用a[10]属于数组越界,平时应该避免这么用;
......
但是, a[10]的值到底是多少?a[10] = 10;
当然 a[11],a[12]等等都是毫无意义的了;
经测试 num = 10, 100, 1000...时,
a[10] = 10; a[100] = 100; a[1000] = 1000;...
求详细解答~ a[num] = num;
关键问题是可否将该语句应用到实际编程中去?
我觉得大伙曲解了我的意思,个人觉得这个应该和数组声明,以及堆栈有关,能否从这个角度给个解答?
另外10,100,1000指的是修改 #define num 10 这个宏~~!
内存给num分配的存储位置紧跟数组a后面,在printf(“%d”, a【num】)时输出了数组a后面地址上的内容,即num的值,该值只读不可修改
追问:
的确,根据不同的环境,改值是会随机发生变化,和我猜想的一样,越界只是访问到了a[num]的这个num所在的位置,才造成的这一结果;谢谢大伙了,但是只能有一个最佳;
追答:
我也用gcc编译器,打印的a【num】是num的值,这一假设的确成立
只是不知道是否可以当成一个惯例来使用
提问者评价
C语言漏洞多多,但是我们得知其所以然!!!
又比如下面这个精心的例子。
大家都知道,在C语言中一般是不会检查数组的下标范围的,这样的好处是给了程序员很大的灵活性,更宜于写出高效的代码。如果定义一个数组a
,其有效下标范围为0 - (n-1),但你要引用下标n,编译器一般是不提示错误的,但是这样也潜在的隐含着一些隐患。
请看如下语句:(32位机器上)
#include <stdio.h>
int main(void)
{
int i;
int a[3] = {1, 2, 3};
for (i = 1; i <= 3; i++)
{
a[i] = 0;
}
return(0);
}
现在我们假设计算机分配给变量i内存位置为0022FF5C
数组a中各元素所分配的内存位置如下:
a[0]地址:0022FF50
a[1]地址:0022FF54
a[2]地址:0022FF58
请看for()循环:
i = 1时,把a[1]置0。i自加一次变为2,把a[2]置0。i再自加变为3。
注意了!!!
当i变为3时,程序将找到数组元素a[3]所在的内存位置(即本例中分配给变量i的内存单元0022FF5C),并写入0,从而导致变量i值为0。接着到for()循环中去判断条件 i <= 3,因为i的值刚才被置为0,i <= 3成立,导致再次开始执行循环。
就后程序将陷入死循环。
这就是C中数组不检查下标的一些隐患。但是现在众多的编译器已经对此缺陷做了设计上改良和优化。
平时写一些有关数组的程序时,对数组的元素个数,最好是采取宏定义的方式,比如#define N 10,或是先把元素个数留空(留空时要记得一定要初始化哦),在用到数组元素个数的时候用sizeof方法计算一下就可以了。比如本例子中可以用sizeof(a)/sizeof(a[0])来计算出数组中所包含的元素的个数。
相关文章推荐
- [LeetCode] Palindrome Linked List
- 一起talk C栗子吧(第二十四回:C语言实例--顺序查找)
- 学习C++的感想
- [C++学习笔记]--动态分配内存空间
- C语言编译过程
- C++ - Identifier not found
- C语言,猜字游戏
- c++ primer 学习笔记-第二章
- 一起talk C栗子吧(第二十三回:C语言实例--队列二)
- C语言缺陷与陷阱(3)
- c++ 复杂类型指针 类指针 浅谈
- C++生产和使用的临时对象
- 对于程序性能优化的理解
- 对于程序性能优化的理解
- C++面向对象编程(五)同名成员变量和同名函数
- 【C++探索之旅】第一部分第三课:第一个C++程序
- 【C++探索之旅】第一部分第二课:C++编程的必要软件
- C++运算符详解问题详解
- 《C++编程思想》(第二版)第3章 C++中的C(笔记、习题及答案)(二)
- 基于Qt5.5.0的sql,C++备忘录软件的编写