| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1839 人关注过本帖
标题:在编程学习过程中遇到的一些很低级的问题,请大侠赐教!
只看楼主 加入收藏
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
回复 9楼 longwu9t
你看看我《麻雀解剖》的帖子,那里就提到extern怎么用,在什么地方用。extern只是外部符号声明,针对模块间数据的。变量声明的范围比extern还要广。

授人以渔,不授人以鱼。
2015-01-03 12:55
longwu9t
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:小飞侠
威 望:6
帖 子:732
专家分:2468
注 册:2014-10-9
收藏
得分:0 
以下是引用TonyDeng在2015-1-3 12:52:14的发言:

之所以局部自动变量未初始化时的值不定,就是因为只有声明无定义,int counter只是声明在本函数中将出现counter这个名称的变量,但并没有真正开辟构建数据实体,只有在执行for()循环中counter = 0的时候,才在栈中创建数据实体,这个时候数据在什么位置是临时找到的,所以它的值不确定,这条赋值语句是把一个常数复制给新创建的数据实体,与定义时初始化马上置值不同(比较一下C++的数据定义方式int counter(0)即知本质区别)。自动变量的值不确定,就是这样来的。相反,对静态变量,编译器是会按默认机制初始化数据的,通常会置零(在C++中就是由类或结构体的构造函数决定初始值)。


谢谢回复 又学习了

[ 本帖最后由 longwu9t 于 2015-1-3 13:09 编辑 ]

Only the Code Tells the Truth             K.I.S.S
2015-01-03 13:07
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
那是各个编译器处理局部变量的方式不同,就如gcc允许vla变量一样,那是它使用栈的方式。所谓标准未定义行为,就是编译器实现自由处理的,那即是不确定。i++,i--的问题就是这样,对某个具体的编译器而言,结论的确的一定的,但这种结论没有可移植性,所以不要试图总结出这类结论。

授人以渔,不授人以鱼。
2015-01-03 13:10
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
对10楼的补充:之所以新标准引入C++的变量即用即声明(定义)语法,道理也在这里,因为本来就是这样实现的,无需再强制程序员写代码时把变量声明集中写在开始处。

授人以渔,不授人以鱼。
2015-01-03 13:13
longwu9t
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:小飞侠
威 望:6
帖 子:732
专家分:2468
注 册:2014-10-9
收藏
得分:0 
程序代码:
#include <stdio.h> 

int A;
int main(void) { 
    static int B;
    printf("A = %d\n", A);
    printf("B = %d\n", B);
    return 0;
}

这一段代码 我试了多个编译器 都能正常通过 A和B也没有显示初始化啊

Only the Code Tells the Truth             K.I.S.S
2015-01-03 13:16
longwu9t
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:小飞侠
威 望:6
帖 子:732
专家分:2468
注 册:2014-10-9
收藏
得分:0 
在论坛里搜了一下,是这样的么?https://bbs.bccn.net/thread-339635-1-1.html
全局变量和静态变量分两种,一种是带初始化的,一种是未初始化的。
可执行程序可以分为几个段,如代码段,主要放指令,数据段,存放已初始化的全局变量和静态变量,即那些初始化的值存放在该段中,该步骤是在链接是就做好了的。还有BSS段,存放未初始化的全局变量和静态变量,这个段在文件中不占空间,当程序加载进内存后,系统给这个段分配空间,并初始化为0,所以未初始化的全局变量和静态变量的值都是0。

Only the Code Tells the Truth             K.I.S.S
2015-01-03 13:24
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
static是静态数据,都自动初始化为零。在函数外部声明int A默认就是static int A,在本模块文件中全局可见、静态。在函数中声明的static int B是函数内部静态数据,在函数内部可见。所有静态数据和函数都在全局区开辟空间储存。


[ 本帖最后由 TonyDeng 于 2015-1-3 13:30 编辑 ]

授人以渔,不授人以鱼。
2015-01-03 13:26
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
不要用过去旧式的执行文件格式解释全部,新式的可执行文件格式有许多,编译器和系统只保证对外的表现符合语言描述,但具体如何实现的则不在我们的研究范围之内,除非你专搞这个课题。现在Windows7以上系统中用VC2012编译的程序,到了XP下就被报告为“不是可执行文件”,就是因为两种系统可执行程序的格式是不一样的;同理,DOS时代的那些段什么的概念,也不是Windows时代仍然适用。

[ 本帖最后由 TonyDeng 于 2015-1-3 13:44 编辑 ]

授人以渔,不授人以鱼。
2015-01-03 13:30
longwu9t
Rank: 11Rank: 11Rank: 11Rank: 11
等 级:小飞侠
威 望:6
帖 子:732
专家分:2468
注 册:2014-10-9
收藏
得分:0 
回复 18楼 TonyDeng
听版主一说,觉得这个问题挺复杂的,似懂非懂之间,还要仔细学习。

Only the Code Tells the Truth             K.I.S.S
2015-01-03 13:49
zklhp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:china
等 级:贵宾
威 望:254
帖 子:11485
专家分:33241
注 册:2007-7-10
收藏
得分:5 
以下是引用TonyDeng在2015-1-3 12:52:14的发言:

之所以局部自动变量未初始化时的值不定,就是因为只有声明无定义,int counter只是声明在本函数中将出现counter这个名称的变量,但并没有真正开辟构建数据实体,只有在执行for()循环中counter = 0的时候,才在栈中创建数据实体,这个时候数据在什么位置是临时找到的,所以它的值不确定,这条赋值语句是把一个常数复制给新创建的数据实体,与定义时初始化马上置值不同(比较一下C++的数据定义方式int counter(0)即知本质区别)。自动变量的值不确定,就是这样来的。相反,对静态变量,编译器是会按默认机制初始化数据的,通常会置零(在C++中就是由类或结构体的构造函数决定初始值)。

但并没有真正开辟构建数据实体,只有在执行for()循环中counter = 0的时候,才在栈中创建数据实体


在C/C++的本地代码里面 这种变量会在函数入口处保留栈空间 相当于开辟数据实体 以楼主的程序为例 函数display_line()的反汇编如下
程序代码:
(gdb) disassemble display_line
Dump of assembler code for function display_line:
   0x000000000040155e <+0>:    push   rbp
   0x000000000040155f <+1>:    mov    rbp,rsp
   0x0000000000401562 <+4>:    sub    rsp,0x30
   0x0000000000401566 <+8>:    mov    DWORD PTR [rbp-0x4],0x0
   0x000000000040156d <+15>:    jmp    0x40157d <display_line+31>
   0x000000000040156f <+17>:    mov    ecx,0x2a
   0x0000000000401574 <+22>:    call   0x402b18 <putchar>
   0x0000000000401579 <+27>:    add    DWORD PTR [rbp-0x4],0x1
   0x000000000040157d <+31>:    cmp    DWORD PTR [rbp-0x4],0x1d
   0x0000000000401581 <+35>:    jle    0x40156f <display_line+17>
   0x0000000000401583 <+37>:    add    rsp,0x30
   0x0000000000401587 <+41>:    pop    rbp
   0x0000000000401588 <+42>:    ret   
   0x0000000000401589 <+43>:    nop
   0x000000000040158a <+44>:    nop
   0x000000000040158b <+45>:    nop
   0x000000000040158c <+46>:    nop
   0x000000000040158d <+47>:    nop
   0x000000000040158e <+48>:    nop
   0x000000000040158f <+49>:    nop
End of assembler dump.

看你的描述 好像赋值之前那块空间是不存在的 这与事实不符啊 你能举个栗子不
2015-01-03 13:50
快速回复:在编程学习过程中遇到的一些很低级的问题,请大侠赐教!
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.014090 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved