元亨利贞t
2019-09-15 07:46
采纳率: 0%
浏览 1.5k

C语言全局变量和静态全局变量和局部变量和静态局部变量在初始化和未初始化时生存期和作用域的具体情况怎么样?

最近看《C程序设计》第五版唐浩强著对静态局部变量有这样一段:

对静态局部变量是在编译时赋初值的,即只赋初值一次,在程序运行时它已有初值。以后每次调用函数时不再重新赋初值而只是保留上次函数调用结束时的值。

如果在定义局部变量时不赋初值的话,则对静态局部变量来说,编译时自动赋初植 0(对数值型交量)或空字符'\0'(对字符变量)。

这里讲静态局部变量在编译赋初值,没有初值自动赋初植 0(对数值型交量)或空字符'\0'(对字符变量)。应该是在编译就分配了空间

在对生存期和作用域解释时又有这样的例子,如图

图片说明

这里讲静态局部变量c的生存期从它所在的函数开始,书上讲“如果一个变量值在某一时刻是存在的,则认为这一时刻属于该变量的生存期,获称该变量在此时刻“存在”“,似乎是说这个静态局部变量从它所在的函数开始才开始在内存分配空间。

是不是赋初值和在内存开辟空间是两个过程,网上有些东西好像是这个意思。还有对全局变量是不是也是编译赋初值?没有初值是不是自动给它赋值(网上好像有这么讲的),那什么时候在内存开辟空间呢(这个图上的生存期从main函数就开始)?

这些可能涉及计算机组成原理,我没学过,希望哪位高手能详细解释下,万分感谢!!!

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

1条回答 默认 最新

  • blownewbee 2019-09-15 09:29

    我想你应该了解一些原则性的东西,这更好帮你理解

    首先,一个总的原则是,c语言是面向效率的语言,它绝对不会初始化。也就是说,某个内存对应某个变量,这个无论是谁分配的,但是除非你赋值,否则它在分配以前存储的是什么,就是什么。这就是你说的“赋初值”。

    然后要说的是,函数里面定义的局部变量,它存储在堆栈上,为什么要存储在堆栈上,因为函数是允许递归调用的,看下面的程序:
    int sum(int n)
    {
    int result = 0;
    if (n == 0) return result;
    result = n + sum(n - 1);
    return result;
    }
    在这个程序里,sum内部又调用了sum,显然,每次调用,都必须有一套独立的result变量的存储,如果只有一个result,那么程序就乱套了。
    所以局部变量使用堆栈,每次调用的时候,自动开辟一个内存,将当前局部变量放上去,当函数调用结束,再自动回收这些内存,此时这个变量的地址就无效了。
    这是为什么局部变量存在生命周期和不需要手工释放的原因。

    全局变量显然只需要一套,你无论在哪个函数里调用,访问某个局部变量都是同一个,所以全局变量没有生命周期(或者说生命周期等于进程执行的时间)。既然全局变量只有一套,又是程序定义好的,所以在程序运行开始的时候就分配好了空间。但是记住我之前说的,c语言任何时候都不会初始化变量,因为初始化变量意味着要往这个内存地址里写入,而C语言不做不必要的事情。

    关于作用域,我再补充说几句
    C语言是一种比较原始的语言,上世纪70年代被设计出来,那个时候的计算机很糟糕,可能还没有你用的手表的运算能力强。因此那时候编写程序,没有什么IDE开发环境,甚至连一个全屏幕的编辑器都没有。
    当很多人一起写程序,然后组合起来的时候,难免会遇到定义了同一个名字的不同变量的问题,这个问题很头痛,因为修改是困难的。C语言给出的变通的办法就是,允许重名的存在,比如
    int a;
    void foo()
    {
    int a;
    ...
    }
    此时局部变量和全局变量重名。那么究竟是认哪一个呢,在函数里,认局部变量a,这个叫做就近原则,在别的函数里,认全局变量a,因为在foo以外,别的地方看不到局部变量a,这就是作用域。
    类似的
    void foo()
    {
    if (...)
    {
    int a;
    }
    a = 123; //error
    }
    在函数里面的块定义的变量,出了块就不认。
    注意作用域和生命周期没有关系。
    生命周期结束,变量所在的内存无效。
    作用域之外,只是说你代码不能访问到这个变量,但是不等于说这个变量存储的地方一定就无效了。

    点赞 打赏 评论

相关推荐 更多相似问题