腾讯微信二货头像工作人员是不是脑残?傻逼?二货?。。。。。。。。。。????????????????

2015年11月 扩充话题大版内专家分月排行榜第一2015年7月 扩充话题大版内专家分月排行榜第一2015年1月 扩充话题大版内专家分月排行榜第一2014年9月 扩充话题大版内专家分月排行榜第一(补)2013年9月 扩充话题大版内专家分月排行榜第一2013年8月 扩充话题大版内专家分月排行榜第一2013年7月 扩充话题大版内专家分月排行榜第一
2016年3月 扩充话题大版内专家分月排行榜第二2015年12月 扩充话题大版内专家分月排行榜第二2015年6月 扩充话题大版内专家分月排行榜第二2015年2月 扩充话题大版内专家分月排行榜第二2014年10月 扩充话题大版内专家分月排行榜第二2014年8月 扩充话题大版内专家分月排行榜第二
2013年6月 C/C++大版内专家分月排行榜第三
2013年 总版技术专家分年内排行榜第三
2012年 总版技术专家分年内排行榜第七
2013年3月 C/C++大版内专家分月排行榜第三
2016年2月 C/C++大版内专家分月排行榜第三2016年1月 C/C++大版内专家分月排行榜第三
2013年 总版技术专家分年内排行榜第三
2012年 总版技术专家分年内排行榜第七
本帖子已过去太久远了,不再提供回复功能。14176人阅读
C 系列(18)
前日,在一次C++课程上,刘老师在举例说明构造函数和析构函数的功能时,提到了全局变量初始化时的构造函数的行为。构造函数在main函数之前初始化全局变量。当然在C++下我是深信不疑的。但随后老师声称C语言下的全局变量也是如此,因为C没有构造和析构函数,所以我们无法看到这一过程,在C++下可以在构造和析构函数中向屏幕打印信息,进而可以观察全局变量的初始化和生存期。
这个观点无疑使我心头一震,作为C的痴迷者,长期以来在我头脑中的印象是,全局变量在编译期就完成初始化了。难道我的观念是错误的?!难道C真的也是在main函数之前,在程序运行初期才初始化?!
于是我翻看了《C语言参考手册》这本书上没有明确的答案,再翻看著名的K&R的《C程序设计语言》中只有括号里面的一句话“在概念上.......”也是含糊其辞。(现在想想这个问题可能和编译器有关,所以丹爷爷也没说明太多)
在网上查询了一下,关于这个问题,持什么观点的都有,没有一个权威的答案。
只能靠自己了,动手实验!
先给出我的结论:
C和C++中的一般全局变量(不包括类class)是在编译期确定的初始值,而不是在程序运行时,在main函数之前初始化的。
C++中的类的全局变量是在程序运行时,在main函数之前初始化的。
预热知识:
C或者C++语言,明面上的入口函数是main(argc,argv),或者tmain、wmain、WinMain等等。但实际上,是C Runtime的startup代码中的void&mainCRTStartup(void)函数,调用了编程者写的main函数。这个函数定义在VisualC++安装目录的crt\src\目录下的某个.c文件中(视VC++的版本不同,存放的文件也不同)。它在执行一些初始化操作,如获取命令行参数、获取环境变量值、初始化全局变量、初始化io的所需各项准备之后,调用main(argc,argv)。main函数返回后,mainCRTStartup还需要调用全局变量的析构函数或者atexit()所登记的一些函数。往深里说,是在链接生成可执行文件时,告诉链接器这个可执行文件的entry就是mainCRTStartup。当然,我们也可以对编译器进行设置,使其不插入mainCRTStartup函数代码
以VC++6.0为例设置:Project-&Settings-&Link 在Category中选择Output,在Entry-point symbol中填上main 即可。
-------------------------
1,&&&&&C语言环境下:
实验准备:
int main(void)
return a+3 ;
在编译器中设置入口函数为main(具体方法见上面)
这样,我们让编译器生成的程序,直接从main函数中进入,而不是先执行mainCRTStartup函数做一些准备工作。
结果预测:
这样,如果函数返回的是3,则说明此全局变量是在编译期就被初始化为0了,如果函数返回的是其它数字,则说明此全局变量是在程序运行时,main函数运行前进行的初始化。
实验结果:
进入控制台(运行cmd命令),运行编译后的程序(因为程序没有向屏幕输出结果,我们看不到任何现象),继续输入命令:echo& %ERRORLEVEL% 则显示3,此即为函数的返回值。
(echo是显示其后的值,系统把前面运行的程序的返回值放在%ERRORLEVEL%中,故我们可以通过此方法获得主函数的返回值)
同理:对于结构体全局变量
int main(void)
return sTest.a+3 ;
函数也返回3.
实验结论:
在C语言中,全局变量是在编译期完成初始化的。
(在本实验中我们没有使用I/O函数把结果打印出来,因为I/O函数的调用之前必须要初始化内存中的某堆空间,而这个工作是由main函数之前的mainCRTStartup函数来做的。而我们设置让编译器跳过这个函数,故会在运行时出错。)
C++语言环境下
实验准备:
A(){a=10;}
int main(void)
return cTest.
结果预测:
这样,如果函数返回的是0,则说明此全局变量是在编译期就被初始化为0了,如果函数返回的是其它数字,则说明此全局变量是在程序运行时,main函数运行前进行的初始化。
实验结果:
在编译器中设置入口函数为main,主函数返回一个其他值
在编译器中设置入口函数为默认,主函数返回值为10
实验结论:
在C++中,类(class)的全局变量是在程序运行期,main函数开始之前,调用类的构造函数完成初始化的。
把C中的代码放到C++下实验
int main(void)
return a+3 ;
结果与C的结果相同。
说明:在C++中一般全局变量的初始化(类除外),是在编译期完成的,而不是在运行期完成。(与C语言规则相同)
mainCRTStartup函数不管一般全局变量的初始化,它管理类(class)的全局变量的初始化,调用类的析构函数。
编译器会在编译时,初始化一般全局变量为0.
另:具有全局生命期的局部静态变量的初始化,与局部变量相同都是在运行时,执行到该初始化语句完成初始化的,只是局部静态变量只初始化一次。
1、程序不是从主函数开始执行的,而是先要执行一些启动代码。(现在明白为什么要在在嵌入式软件编程时要在工程中添加类似于75x_init.s和75x_vect.s这两个汇编文件了吧)
2、你应该给主函数以返回值。实际上标准C只规定了两种形式的main函数:
int main( void ) 和 int main(int argc, char *argv[])
main返回0,告诉系统程序正常终止,返回非零值告诉系统程序异常关闭.
其作用:我们可以利用程序的返回值,控制要不要执行下一个程序。
例:程序名&&DOS命令
前面的程序正常执行后才执行后面的DOS命令。当然我们也可以用其它的逻辑符把程序和命令组织起来,来实现复杂的功能。
(UNIX中的shell命令也有类似功能)
&&相关文章推荐
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:432322次
积分:3988
积分:3988
排名:第7083名
原创:68篇
评论:162条
阅读:79903
文章:13篇
阅读:35923
文章:15篇
阅读:149610C语言中变量的位置与程序优化_C语言中文网
&&/&&&&/&&
前几天一个朋友在网上问我:&怎么区分全局变量,静态变量和自动变量?&我觉得奇怪,他怎么问一个初学者的问题,我这位朋友其实编程挺厉害的,呵呵。接着他说是:&计算机怎么区分&。确实,人区分各种变量一看就知道了,但是计算机怎么区分呢?没有编译知识可能一下子也难弄懂。
计算机理解力是没法和我们相比的,但是它比我们快。我们可以把这些变量分开来放,从不同地方取来的就是不同的变量。告诉计算机去找的就是符号表。当然,生成符号表是编译器的事,我们不用管。但是了解一点总是有好处的。这里我以Unix ELF(Executalbe and Linkable Format)格式文件为例说明编译器是怎么安排全局变量,静态变量和自动变量的位置的。
ELF可重定位目标文件包括:ELF头以及.text,.rodata, .data ,.bss ,.symtab, .rel.text, .rel.data 等节。
1、全局变量:已初始化的保存在.data段中 ,未初始化的表示为.bss段的一个占位符;
2、静态变量:根据是否初始化分别在.data 和.bss段中分配空间;
3、自动变量(非静态局部变量):在运行时保存在栈中。既不在.data 段中也不在.bss段中。
其实我们可以编写一个简单的程序,编译了以后用objdump命令查看各种变量所在的节。
知道了各种变量在运行时的位置也就知道了他们的储存期,而且了解变量的位置对编写高性能程序也非常有帮助。
我们知道嵌入式对程序的性能要求是非常高的,函数的参数列表越长那么函数调用的开销就越大,这个时候我们可以使用全局变量提高程序的性能。将函数和变量声明为static可防止函数和变量被其它模块不正确的使用。
关于自动变量,请看下面的两个程序:
void factorialA(long n)
&&&&&&&& for(i = 1; i &=i++ ){
&&&&&&&& product *=
void factorialB(long n)
&&&&&&&& long x = 1;
&&&&&&&& for(i = 1; i &=i++ ){
&&&&&&&&&&&&&&&&& x *=
&&&&&&&& }&
&&&&&&&& product =
在n值较大的时候,上面两个程序的性能是有显著差别的。 这是利用了程序的局部性原理。
推荐文章 TOP10—————————————————————————————————————————————————————————————————————————————
只有不断的学习,不断的进步,才能不被替代!
只有你的不可替代性才决定你的价值!
—————————————————————————————————————————————————————————————————————————————
第一部分问题:
今天一个小伙伴问我一个问题,如图程序1:
咋一看没有问题啊,后来想想确实有问题,这个c=a+a;似乎是语句,必须在函数体内才能执行,后来就看到这么一句话:
赋值语句需要有函数执行,c语言最基本的执行体是函数,你可以初始化,但不能在函数体外赋值。
在VC++中,确实出错,指针的地方出错,错误提示:
错误说的是:初始化必须是一个常量。
然后我就去掉运算的c。如图程序2:
显示可以正常运行的。然后就比较郁闷,就问了QQ好友(矩阵)。正确答案如下:
函数体外只能进行初始化,不能进行赋值运算。如图程序3:
提示的错误是:变量a被重复赋初值。
其实正确的理解就是:函数体外只能进行初始化,不能进行赋值运算。为什么第二个程序可以执行?
因为,C语言执行过程中,对代码进行了优化,把程序2中的 a=10; &优化为一句话:int a=10;这就是初始化。所以程序2是正确的,程序3中,初始化过程中:int a=10;int a=17;肯定就出错了。重复初始化。程序1中,语句必须在函数体内执行,函数体外只能进行初始化。
第二部分全局变量与局部变量
局部变量(Local Variable):定义在函数体内部的变量,作用域仅限于函数体内部。离开函数体就会无效。再调用就是出错。
全局变量(Global Variable):定义:所有的函数外部定义的变量,它的作用域是整个程序,也就是所有的源文件,包括.c和.h文件。
全局变量的例子,如图程序4:
提示的错误是 变量 x 没有定义,原因是:
C语言代码是从前往后依次执行的,由于 x 定义在函数 func1() 之后,所以在 func1() 内无效;修改程序如下,程序5:
可以看出,输出正确的答案,所以全局变量必须定义在我们需要用它的函数体之前。
然后,在看下局部变量:
注意事项:
①在main函数中定义的变量也是局部变量,只能在main函数中使用;同时,main函数中也不能使用其他函数中定义的变量。main函数也是一个函数,与其它函数地位平等。
②形参变量、在函数体内定义的变量都是局部变量,实参给形参传值的过程也就是给局部变量赋值的过程。
③可以在不同的函数中使用相同的变量名,它们表示不同的数据,分配不同的内存,互补干扰,也不会发生混乱。
④在语句块(由一对{}包含的若干条语句)中也可以定义变量,它的作用域只限于当前的语句块。
一道综合练习题:
①先调用fun1(),在fun1()中,有局部变量n,所以输出的结果是 &n:20;
②对于fun2(),使用了形参,形参的作用范围也是整个函数内(实参给形参传值的过程也就是给局部变量赋值的过程),所以输出的结果是 &n:30;
③对于fun3(),没有局部变量,所以全局变量定义的 n 对所有的函数都可见。所以输出的结果是 &n:10;
④根据局部变量注意事项第四条。所以输出的结果是 &n:40;
⑤3C语言规定,只能从小的作用域向大的作用域中去寻找变量,而不能反过来,使用更小的作用域中的变量。对于 main() 函数,即使代码块中的 n 离输出语句更近,但它仍然会使用 main() 函数开头定义的 n,所以输出结果是 30。
所以结果是:
第三部分内存的分区和变量的存储
内存中供用户使用的存储空间分为三部分:程序区 &、静态存储区、动态存储区。
变量的分类:
①从空间上分配:从变量的作用域可以分成:局部变量和全局变量。
②从变量的存在时间(生存周期)可以分成:静态存储和动态存储。
静态存储:程序在运行期间分配固定的存储方式。
动态存储:程序在运行期间根据需要动态的分配存储空间。
全局变量全部存储在静态存储区。在程序开始执行过程中给全局变量分配空间,程序执行完毕就释放空间。程序执行过程中固定的分配空间,而不需要动态进行分配是释放。
动态存储区主要存放以下数据:函数的形参、自动变量(没有加static的局部变量)、函数调用的现场现场保护和返回值。
动态存储区的数据,在函数开始调用时分配动态存储空间,函数结束时释放这些空间。
C语言中每个变量有两个属性:第一数据类型;第二存储属性。
auto 变量:
函数中的局部变量,如果不专门的声明为 static存储,都是动态分配存储空间。数据存储在动态存储区内。函数中的形参和函数中的变量都属于此类,调用该函数时候系统自动的分配空间,在函数结束的时候,释放该空间。这些局部变量被称为自动变量。自动变量用 auto关键字声明(可以省略auto )。
static 变量:
有时候希望我们调用的函数在释放的时候不消失能保留原值,这就需要定义为静态局部变量。用关键字 static声明。
看一段程序:
对静态局部变量的说明:
1)静态局部变量属于静态存储类别,在静态存储区内分配存储单元。在程序整个运行期间都不释放。而自动变量(即动态局部变量)属于动态存储类别,占动态存储空间,函数调用结束后即释放。
2)静态局部变量在编译时赋初值,即只赋初值一次;而对自动变量赋初值是在函数调用时进行,每调用一次函数重新给一次初值,相当于执行一次赋值语句。
3)如果在定义局部变量时不赋初值的话,则对静态局部变量来说,编译时自动赋初值0(对数值型变量)或空字符(对字符变量)。而对自动变量来说,如果不赋初值则它的值是一个不确定的值。
register变量
为了提高效率,C语言允许将局部变量得值放在CPU中的寄存器中,这种变量叫“寄存器变量”,用关键字register作声明。
1) 只有局部自动变量和形式参数可以作为寄存器变量;
2)一个计算机系统中的寄存器数目有限,不能定义任意多个寄存器变量;
3)局部静态变量不能定义为寄存器变量。
用extern声明外部变量
外部变量(即全局变量)是在函数的外部定义的,它的作用域为从变量定义处开始,到本程序文件的末尾。如果外部变量不在文件的开头定义,其有效的作用范围只限于定义处到文件终了。如果在定义点之前的函数想引用该外部变量,则应该在引用之前用关键字extern对该变量作“外部变量声明”。表示该变量是一个已经定义的外部变量。有了此声明,就可以从“声明”处起,合法地使用该外部变量。
extern 例子:
在 main 函数体外定义的变量,A 、B(外部变量:它的作用域为从变量定义处开始,到本程序文件的末尾。)。想要在main中引用必须加关键字:extern 。
第三部分:C语言的堆与栈
和栈的第一个区别就是申请方式不同:栈(英文名称是stack)是系统自动分配空间的,例如我们定义一个 char a;系统会自动在栈上为其开辟空间。而堆(英文名称是heap)则是程序员根据需要自己申请的空间,例如malloc(10);开辟十个字节的空间。由于栈上的空间是自动分配自动回收的,所以栈上的数据的生存周期只是在函数的运行过程中,运行后就释放掉,不可以再访问。而堆上的数据只要程序员不释放空间,就一直可以访问到,不过缺点是一旦忘记释放会造成内存泄露。
&&相关文章推荐
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:12986次
排名:千里之外
原创:72篇
(3)(4)(19)(5)(1)(4)(1)(2)(6)(8)(23)(1)}

我要回帖

更多关于 二货哥之兄弟一起闯 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信