首页 > 试题广场 >

在32位系统下运行以下程序,可能的输出结果为( ...

[单选题]
在32位系统下运行以下程序,可能的输出结果为()
int main () {
    int i,a[5];
    for (i = 0; i <= 30; i++) {
        a[i] = 0;
        printf("%d:hello\n", i);
    }
    printf("%d:hello world",i);
    return 0;
}


  • 三十行的 i:hello (i∈[0,30]) 和一行 30:hello world
  • 三十行的 i:hello (i∈[0,30]) 和一行 31:hello world
  • 多行的 i:hello (i∈[0,30] )
  • 多行的 i:hello (i∈[0,31])
我看了这道题的解析  写的都不是特别的清晰
于是自己写了一下,希望能认真的看完,我相信你是有收获的
如果觉得好就点个赞  谢谢😀

首先你一定要知道,数组溢出是不会报错的。
我们由上图 可知: i  和  a[5] 是同一个地址  ,所以  当循环到  a[5]=0时   i也为  0
故就一直循环,造成了死循环。于是本题选C
再看一幅图 来扩展一下:

你会发现这次的i  和 a[5]  不是同一个地址了  看我圈住的部分你会发现两者之间的区别:
我觉得是这样的(可能不是特别的准确):
图一:   int   i,a[5];
从右到左 定义   所以  a[0]是高地址  以此类推  所以 a[5]和  i  是同一个地址
图二:     int   a[ 5] ,i ;
从右到左 定义   所以  i  低地址  以此类推  a[0],a[1]-----所以 a[5]和  i  不是同一个地址
这时候我有了一个猜想:  就是先定义的是高地址,后定义的是低地址
下面来实验一下,验证猜想:

猜想正确。
如果觉得好就点个赞  谢谢😀
编辑于 2020-07-14 20:42:00 回复(10)
本题是考察数组越界会导致死循环。经过实验得知,当循环体中改为i<=7后,开始0-6的死循环,i<=6及之前的,都可以退出循环。
栈中是从高地址指向低地址的,如下:
高地址 | i | a[4] | a[3] | a[2] | a[1] | a[0] | 低地址
所以i在高地址,而数组是连续存储的,而又由于有些编译器做了优化,使数组和i之间留有内存间隙,如开头所述,我用的VS2010留了2个间隙,但是,如果i越界严重,比如不小心给了50,还是会导致死循环。知a[6]与i占据一块空间,当执行到i=6,a[6]=0,将i的值又变成了0,又进入循环段执行下去,i永远的不大于30,造成死循环
编辑于 2019-08-24 14:02:14 回复(7)
  看了一下下面的解说都不太好懂,我来说一个好懂的。首先这是一个main函数,是函数就会在栈上开辟一块空间,就要遵守栈空间的一些规则。题目先定义int i后定义int a[5](这是压栈,因为栈空间是先用高地址在用低地址,所以int i在高地址 int a[5]相对于在低地址,其中注意int a[5]排布是a[4] | a[3] | a[2] | a[1] | a[0] )压栈完以后开始出栈,出栈是从低到高(也就是从a[0]开始)一步一步往上执行,因为循环次数大于数组个数,他改变完数组变量的值,还会继续向上执行,把最顶层的int i的值给改变成0,这样又符合循环规则了,继续执行打印函数。
修改程序有两种方法,一是将循环次数修改为小于等于数组个数;二是将int i和int a[5]定义的先后顺序调换一下位置。
第一次发解析,有错请见谅,可以在下面回复。
发表于 2022-02-06 15:33:33 回复(4)
C++数组越界不报错,i声明在a之前,i相较于a位于高地址,a[i]=0会把i的值改变
如果i声明在a之后,则相较于a位于低地址,不会被a[i]=0冲掉
发表于 2020-05-09 10:11:26 回复(0)
c语言数组越界不会报错
发表于 2019-09-05 22:40:37 回复(2)
真服了这题 应该选B 你们自己都不敲代码的嘛??? 代码告诉你选B了 真正分析起来就是变态 题目 首先先明确 函数调用栈 参数的入栈顺序是 后定义的变量先入栈,数组元素之间也一样 所以入栈顺序是 高地址 a[4] a[3] a[2] a[1] a【0】i 低地址 对数组a赋值 是从a【0】开始向高地址 溢出 根本不会覆盖掉 变量i的值 当然会正确执行 所以答案是B 但是将 定义变量改为 int a【5】,i; 这样栈空间的变量排布为 高地址 i a[4] a[3] a[2] a[1] a【0】 低地址esp 这样对a【5】赋值会覆盖掉i的值 会进入死循环 才会选C 这出题的人自己都没弄明白 就瞎给答案 这道题其实和编译器和 栈空间增长方向都有关 要不就是死循环,要不就是正常打印然后报个段错误
编辑于 2021-11-08 12:37:55 回复(5)
发表于 2022-11-24 18:31:35 回复(0)
#include<stdio.h>
int main() {
	int arr[5];
	int i;
	for (i = 0; i <= 30;i++) {
		arr[i] = 0;
		printf("%d,hello\n",i);
	}
	printf("%d,hello out", i);
	return 0;
}
我的打印的结果是B,这题目答案给错了吧😂😂😂
发表于 2021-07-18 15:38:05 回复(6)
手机直接卡死……!!
发表于 2019-11-24 23:44:52 回复(0)
各位大神可以给分析一下,吗
发表于 2019-08-19 16:26:25 回复(0)
话不多说让我们打印看看吧!
上图1:
这是VS里x86的调试结果,也就是32位机子的结果;大大滴死循环,根本都走不出for,更别提hello world了,之所以第7位就是a数完a[4]过俩空后到i结果又置0了;编译器会给i和数组留2个空隙,这还是我从讨论里得知的 我说怎么循环在第7位呢!
上图2: 
这是VS里x64的调试结果,也就是64位机子的结果;会在结尾报个错误但是打印还是照打出31行
发表于 2024-08-06 16:41:00 回复(0)
这应该跟栈后进先出的特性有关,它是从高地址往低地址分配内存的。
而在数组内部,数组中的元素从低地址到高地址依次分配。(因为栈只能获取栈顶的内存地址,即处于最低位的数组起始地址
发表于 2023-10-14 22:45:09 回复(0)
栈先用高地址 i首先被放在高地址 而数组地址是从低到高的 此时就可能因为越界访问而修改了i的值 如果先定义数组再定义i就不会出现这种情况。
发表于 2023-03-23 18:14:44 回复(0)
数组越界导致的死循环
发表于 2022-09-07 09:45:10 回复(0)
为什么牛客都是这种脑瘫题啊?都2202年了,全是ub行为。
我祝牛客开发下次跳槽的时候考的全是这种题。
发表于 2022-04-02 01:36:36 回复(2)
这道题目考察了 C 中函数变量在栈上的内存布局,和进程地址空间的内存布局.
需要明确两点: 
  1. 在经典的进程地址空间的内存布局中,栈是一块连续的内存空间
  2. 栈的内存空间对应: 栈底高地址,栈底滴地址.eg: 假设一个栈容量为 1M 起始地址为0x00结尾地址为0x400,那么栈底对应 0x400,栈顶对应 0x00
明确了以上两点,再回到这个题目上.可以清楚的看到该main 函数调用栈中,栈底为 int i,然后紧跟着是 int a[5],其余再无变量.
在循环中,当i为6及以上时,数组指针 a 已经越界了,假设编译器没有任何防止数组越界的优化.那么当a第一次为的时候,*a=0,就是把i的值设置为了0(不容易理解的话,画一个图,|i,a,a,a,a,a,|,此时a指向i),所以程序无限循环
.注意:(一般编译器为了防止简单的数组越界,(比如超限访问 1个或2个元素)一般会为数组多分配数组容量+N的内存(不同编译器实现不同,UB行为))
题外话,根据数组的越界访问保护这一行为,后面在c++ stl 中延伸出了end()迭代器的位置确认

编辑于 2021-02-20 11:33:13 回复(2)
这是c语言的题??我明明做的java题呀
发表于 2019-09-24 18:26:42 回复(0)
为什么可以越界
发表于 2019-08-22 11:08:59 回复(1)
越界了不是要报错吗
发表于 2019-08-22 07:51:58 回复(2)
数组引用越界了吧
发表于 2019-08-20 09:38:48 回复(0)