鱼C论坛

 找回密码
 立即注册
查看: 2812|回复: 7

[已解决]C语言【全局变量初值】和【入栈顺序对全局变量终值影响】的问题

[复制链接]
发表于 2017-6-30 09:09:28 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 fergus1987 于 2017-6-30 14:03 编辑


不知为何前两天发的贴被删掉了??首先感谢前一帖中为我解惑的大神(名字忘记抱歉)!
在此重开一帖继续虚心求教两个问题!!

参考程序(将输入的十个数值用同一个函数分别输出均值、最大值、最小值)如下:

#include<stdio.h>

float Max,Min;

int main()
{
    float ave(float a[],int n);
    int i;
    //float b[10]={89,95,87.5,100,67.5,97,59,84,73,90},average;
    float b[10];
    printf("input 10 scores:");
    for(i=0;i<10;i++)
    {
        scanf("%f",&b[i]);
    }
    printf("Ave=%f\nMax=%f\nMin=%f\n",ave(b,10),Max,Min);
    return 0;
}

float ave(float a[],int m)
{
    int i;
    float x=a[0];
    Max=Min=a[0];
    for(i=1;i<m;i++)
    {
        if(a[i]>Max)
            Max=a[i];
        else if(a[i]<Min)
            Min=a[i];
        x+=a[i];
    }
    x=x/m;
    return(x);
}
疑问1、全局变量初值

如下图所示

1.png

程序并未对全局变量Max和Min赋初值,但在debug中发现系统自动为Max和Min赋0值,不知为何?
这与之前学习的局部变量不一样,印象中未赋初值的局部变量在debug中的值是一段内存地址?

疑问2、入栈顺序对全局变量终值影响

如下图所示

2.png


main函数中printf函数自右向左先后输出的是Min、Max和ave函数,因变量Max和Min在ave函数中被赋值,但按入栈顺序,此时输出的Max和Min值应为初始值0,所以可以看到dos框中该两个变量的值没有问题。

但debug中程序运行结束时可以看到查询变量值窗口中的Max和Min却是被赋给了经过ave函数处理后的值??

初学C,就这两个问题请教各位!请不吝赐教!


最佳答案
2017-6-30 17:37:59
0x0040140d <main+90>:        movl   $0x7,0x4(%esp)     
0x00401415 <main+98>:        lea    -0x48(%ebp),%eax
0x00401418 <main+101>:        mov    %eax,(%esp)
0x0040141b <main+104>:        call   0x4012f0 <foo>  
0x00401420 <main+109>:        fldl   0x404090         
0x00401426 <main+115>:        fstpl  0x14(%esp)
0x0040142a <main+119>:        fldl   0x4040a0
0x00401430 <main+125>:        fstpl  0xc(%esp)
0x00401434 <main+129>:        fstpl  0x4(%esp)
0x00401438 <main+133>:        movl   $0x403007,(%esp)
0x0040143f <main+140>:        call   0x4019c0 <printf>

可以看到汇编里面是 先调用了 foo
然后
0x404090   入栈
0x4040a0   入栈
一直到调用printf
新建位图图像.jpg
从这个运行截图可以看到
0x404090 是min的地址
0x4040a0 是max的地址
        printf("%f %f %f\n", foo(arr, sizeof arr/sizeof *arr), max, min);        
这里的入栈顺序是从右向左的
但函数foo会在函数入栈之前调用

而在你的编译器中 入栈顺序是从右向左的
但函数调用会在 min max入栈之后
这就是我为什么说输出什么无法确定
函数调用有可能发生在min max入栈之前
也有可能发生在min max入栈之后

另一个问题
本来就可以直接定义
书里面没说吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2017-6-30 09:31:41 | 显示全部楼层
请参考 http://blog.csdn.net/u014181676/article/details/22103265
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-6-30 10:25:33 From FishC Mobile | 显示全部楼层
代码是错的
和入栈顺序无关
这是未定义行为
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-6-30 10:28:16 From FishC Mobile | 显示全部楼层
全局变量 静态变量
都会自动初始化为0值
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-6-30 10:49:01 | 显示全部楼层
时输出的Max和Min值应为初始值0

实际上 会输出什么无法确定
你运行结果输出 0 0
换一个编译器输出可能就这样了
新建位图图像.jpg
这是一段错误的代码
你对这代码的理解只是牵强附会
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-6-30 14:12:34 | 显示全部楼层
求道于盲 发表于 2017-6-30 10:49
实际上 会输出什么无法确定
你运行结果输出 0 0
换一个编译器输出可能就这样了

谢谢指点!!对于你给出的代码有两点疑惑:

1、你所说的“会输出什么无法确定”是指printf函数的输出是没有出栈顺序的?从你的代码知道此时printf函数是从左向右输出的,因为输出结果,max和min被赋了新值了

2、为什么你的代码中没有在main函数中对foo函数进行申明?而直接进行定义了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-6-30 17:37:59 | 显示全部楼层    本楼为最佳答案   
0x0040140d <main+90>:        movl   $0x7,0x4(%esp)     
0x00401415 <main+98>:        lea    -0x48(%ebp),%eax
0x00401418 <main+101>:        mov    %eax,(%esp)
0x0040141b <main+104>:        call   0x4012f0 <foo>  
0x00401420 <main+109>:        fldl   0x404090         
0x00401426 <main+115>:        fstpl  0x14(%esp)
0x0040142a <main+119>:        fldl   0x4040a0
0x00401430 <main+125>:        fstpl  0xc(%esp)
0x00401434 <main+129>:        fstpl  0x4(%esp)
0x00401438 <main+133>:        movl   $0x403007,(%esp)
0x0040143f <main+140>:        call   0x4019c0 <printf>

可以看到汇编里面是 先调用了 foo
然后
0x404090   入栈
0x4040a0   入栈
一直到调用printf
新建位图图像.jpg
从这个运行截图可以看到
0x404090 是min的地址
0x4040a0 是max的地址
        printf("%f %f %f\n", foo(arr, sizeof arr/sizeof *arr), max, min);        
这里的入栈顺序是从右向左的
但函数foo会在函数入栈之前调用

而在你的编译器中 入栈顺序是从右向左的
但函数调用会在 min max入栈之后
这就是我为什么说输出什么无法确定
函数调用有可能发生在min max入栈之前
也有可能发生在min max入栈之后

另一个问题
本来就可以直接定义
书里面没说吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2017-7-3 16:29:33 | 显示全部楼层
求道于盲 发表于 2017-6-30 17:37
可以看到汇编里面是 先调用了 foo
然后
0x404090   入栈

再次感谢!由于C刚入门,还没有学习过汇编,所以理解得不透彻!

关于第二个问题,书上是重点强调过调用函数前一定要先申明,但通过百度+自己验证了解到:函数调用出现在函数定义之后,可以不加申明
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-28 08:31

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表