转:extern 与 static 关键字的完整说明

[复制链接]
4649|4
 楼主| tedyu 发表于 2009-5-13 16:30 | 显示全部楼层 |阅读模式
先分清C和C++再解释,有不同之处<br /><br />1.&nbsp;C语言:<br /><br />1.1.&nbsp;首先要明确三个概念:<br />声明vs定义&nbsp;——&nbsp;声明只规定对象的“类型”,定义则规定了对象的“实体”。一个对象,声明可以无穷多次,定义只能一次!<br />作用域&nbsp;——&nbsp;指对象的“存取权限”<br />存储方式&nbsp;——&nbsp;指变量为“静态数据段DS”或“堆栈段”变量<br /><br />1.2.&nbsp;对变量(变量有“存储方式”的问题):<br />extern:声明/定义变量,作用域=全局,存储方式=DS<br />static:定义变量,作用域=局部,存储方式=DS<br /><br />extern声明的同时给变量赋了初值,那就同时做了定义,否则就只是声明<br />所以<br />extern&nbsp;int&nbsp;var&nbsp;=&nbsp;0;<br />之类的东西是不应该出现在.h文件里的,而且在一个程序里只能出现一次,否则就是重复定义了<br /><br />static变量如果出现在函数内,作用域只在函数内,否则就是当前文件。<br /><br />函数内用static局部变量的意图不在于作用域,而在于将存储方式强制规定为静态,使“再入”时仍保持上一次的值。同一函数的所有“副本”都公用一个该变量的实体,因此使用了static变量的函数一般是“不可再入”的,不是“多线程安全”的。<br /><br />1.3.&nbsp;对函数(函数无所谓“存储方式”):<br />extern:声明/定义函数,作用域=全局<br />static:声明/定义函数,作用域=局部<br />extern/static如果只跟函数原型,就是声明,如果跟了函数体,就是定义。(有人不知道static也可以只声明不定义)<br />如果声明时指定了extern或static的,定义时可以省略extern/static,如果不省略,必须一致。<br /><br />2.&nbsp;C++语言:<br />C++是C的超集,所以包含了上述特性,只是多了在类中使用static,和extern&nbsp;&quot;C&quot;的用法<br />类中使用static将成员声明为“静态”,类static成员的作用域是全局的,而非局部的(当然受privite/protected限制),且该类所有实体公用一个static成员实体,意图在于存储方式,不在作用域。<br />与其它成员不同,static成员需要单独的实体定义。<br />与C语言不同,类static成员在定义时,不能再用static修饰。<br /><br />extern&nbsp;&quot;C&quot;&nbsp;则是为了C++与C混合编程而设的<br /><br /><br />C/C++语言的extern/static/auto等关键字将声明/定义/作用域/存储方式等职能混在一起,为了减少关键字数量而没有分工,不规则,规定复杂,实在是给初学者出难题,我个人觉得设计得不好(但也许是能做到的当中最好的了),我见过编了十几年C程序的人还是有不会用的时候。<br />
high 发表于 2009-5-14 01:18 | 显示全部楼层

这几个

玩10年的弄不明白要打pp的。&nbsp;auto没有见过可以理解,其他的不知道就打pp。(不需要模块化编程的单片机除外)<br /><br />要是补充个volatile,&nbsp;#pragma&nbsp;pack,&nbsp;__packed,&nbsp;__align...这些的说明就完美了。
high 发表于 2009-5-14 01:56 | 显示全部楼层

我知#pragma pack(n)是标准c

关于数据对齐<br /><br />所有的内存数据访问可以分为以下类别:<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;*<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;自然对齐,例如,在位于&nbsp;0x1000&nbsp;的字边界上。&nbsp;ARM&nbsp;编译器通常对齐变量并填充结构,使得可以使用&nbsp;LDR&nbsp;和&nbsp;STR&nbsp;指令有效访问这些项。<br />&nbsp;&nbsp;&nbsp;&nbsp;*<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;已知但并非自然对齐,例如,位于地址&nbsp;0x1001&nbsp;的字。&nbsp;此类对齐通常出现在压缩结构以删除不必要的填充时。在&nbsp;C&nbsp;和&nbsp;C++&nbsp;中,__packed&nbsp;限定符或&nbsp;#pragma&nbsp;pack(n)&nbsp;编译指令用于表示结构已压缩。<br />&nbsp;&nbsp;&nbsp;&nbsp;*<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;未知对齐,例如,位于任意地址的字。&nbsp;此对齐类型通常出现在定义可以指向位于任何地址的字的指针时。在&nbsp;C&nbsp;和&nbsp;C++&nbsp;中,__packed&nbsp;限定符或&nbsp;#pragma&nbsp;pack(n)&nbsp;编译指令用于表示指针可以访问位于非自然对齐边界的字
high 发表于 2009-5-14 02:15 | 显示全部楼层

armv6以上的版本就支持非对齐访问了。

举个例子看看我理解对吗<br /><br />typedef&nbsp;unsigned&nbsp;int&nbsp;DWORD;<br /><br />ReadDevice((char*)0x10000001);<br /><br />int&nbsp;ReadDevice(char&nbsp;*&nbsp;pbuf)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;形参是char&nbsp;*pbuf,&nbsp;会不会出现指向一个非4字节对齐的地址?<br />&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;可能性存在,虽然不是很大。<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;DWORD&nbsp;deviceBuf[1024];&nbsp;//&nbsp;赶巧,因为设备接口,或者使用了DMA,就是4字节的缓冲。<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;__packed&nbsp;DWORD&nbsp;*&nbsp;p&nbsp;=&nbsp;(DWORD*)pbuf;&nbsp;//&nbsp;带了__packed关键字的就可以访问非对齐地址了。<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;((unsigned)&nbsp;pbuf&nbsp;&&nbsp;0x3)&nbsp;{&nbsp;//&nbsp;不对齐了。<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*p&nbsp;=&nbsp;deviceBuf[0];<br />&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;*pbuf&nbsp;=&nbsp;deviceBuf[0];<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />}
您需要登录后才可以回帖 登录 | 注册

本版积分规则

36

主题

52

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部