2005年八月月 发布的文章

走马观花ANSI C标准-标识符

标识符(identifier)

1、一个标识符可以表示:
a) 对象(object)
b) 函数(function)
c) 结构体(struct)的标签(Tag)[注1]
d) 结构体的成员
e) 联合体(union)或枚举类型(enumeration)
f) 类型别名(typedef)
g) 标签(label)
h) 宏(macro)
i) 宏参数(macro parameter)
同一个标识符在程序的“不同点”处可以表示不同的“实体”(entity)。[注2]
一个枚举(enumeration)的成员被称为一个“枚举常量,enumeration constant”。

2、作用域(Scope)
Scope共定义了四种:
a) 函数作用域(function)
b) 文件作用域(file)
c) 块作用域(block)
d) 函数原型作用域(function prototype)

标签名(label name)是唯一一个拥有“函数作用域”的标识符。它可以用在它所在函数内的任何位置。

标识符拥有的作用域取决于它声明时的位置。
如果标示符声明在任何块(block)或者函数定义的参数列表外的话,那么它拥有“文件作用域”,它的作用域同所在“翻译单元”;
如果标示符声明在任何块(block)或者函数定义的参数列表内的话,那么它拥有“块作用域”,它的作用域同所在“块”;
如果标示符声明在函数原型的参数列表内的话,那么它拥有“函数原型作用域”,它的作用域同所在的“函数原型”。

一个原则:“内层作用域,inner scope”的标识符会隐藏(hide)“外层作用域,outer scope”的标识符。

3、标识符的链接(linkages of identifiers)
在不同Scopes或者同一个Scope下声明不止一次的标识符,进程会将它们参考到(refer to)同一个object或function,这就被称为“linkage”。注意:在不同的标识符之间没有linkage可言。
标准定义了3种linkage:
   a) external
   b) interal
   c) none

1) 在组成一个完整程序的“翻译单元”和“库”中,拥有external linkage的标识符指示同一个object or function;
2) 在一个“翻译单元”内,拥有internal linkage的标识符指示同一个object or function;
3) 一个“文件作用域”的标识符,如果前面有“static”修饰,那么该标识符拥有“internal linkage”;
4) 一个没有任何存储类型(storage-class)修饰的函数标识符与使用extern修饰的函数标识符的linkage相同;
5) none linkage情况:
   a) 一个被声明为既不是object又不是function的标识符;
   b) 一个被声明为函数parameter的标识符;
   c) 一个被声明为object,拥有block scope,但无extern修饰的标识符。

[注1]
关于“结构体的标签”我们举例说明:
struct point_t {
 int x;
 int y;
};
point_t被称为“结构体的标签”,注意在ANSI C中“结构体的标签”不是类型,不能单独使用。必须和struct联合使用。
如:point_t origin; /* error */
    struct point_t origin; /* ok */

[注2]
关于这句话“同一个标识符在程序的“不同点”处可以表示不同的“实体”(entity)”还是很好理解的。一般都是由于Scope的不同。例如:

src1.c中的static int count和src2.c中的同名的static int count。

走马观花ANSI C标准-环境

标准都是条条框框的,以严谨著称,语言晦涩难懂。这也是大多数人不愿意“接近”它的原因。但它吸引我的最重要原因恰恰是“标准”二字,我觉得我能从这个标准中找到一些“闪光点”,而这些“闪光点”又恰恰是能让我有所提高的地方。

1、翻译环境
C Source文件是以文本形式存在的,将之转变成可执行程序的过程,我们管之叫“翻译”。C语言的翻译不是一蹴而就的,一般需要两遍才能达到目的,第一遍称为“预处理”,预处理的基本单位是“预处理翻译单元”。第二遍叫“编译”,编译的基本单位是“翻译单元”

a)何为“预处理翻译单元”?
其实很多人之前对这个的理解都很模糊,标准中是如是说的“一个预处理翻译单元是由一个Source file和该Source file通过#include指示符包含的Header files和Source files组成的”,不妨多看几次这个说明,标准就是标准,理解起来还真有些费事^_^。注:#include "xx.c"是没有错误的,只是不常用。

b)“预处理翻译单元”和“翻译单元”之间的关系
预处理后的“预处理翻译单元”叫“翻译单元”。

c)“翻译单元”之间的关系
首先翻译单元相互独立编译;
其次一个完整的可执行程序是由众多翻译单元链接而成的;
最后翻译单元之间是“external linkage(外部链接)”的关系。

2、执行环境
经过复杂的翻译后,现在我们拥有了可以执行的程序了。我们要关心的就是我们的“执行环境”了。执行环境分为两类:“独立的”和“宿主的”。都很好理解。前者在实现时没占一点操作系统的便宜。后者则恰恰相反,利用了很多操作系统的特性和现成的东东。

我们所使用的执行环境多为后者。启动函数(Startup function)一般为main,main有两种原型形式:
int main(void);
int main(int argc, char *argv[]);
当然对第二个main的参数有些限制。如argc >= 0等。

3、其他考虑
a)字符集
源文件字符集:用于书写源文件的字符集。
执行字符集:在执行环境中被解释的字符集。
基础字符集:包括26个小写拉丁字母、26个大写拉丁字母、数字0~9等,这些字符的值都能用8位bit(即一个字节)编码表示。我的理解如ASCII字符集
扩展字符集:一些非基础字符集的区域相关(locale-specific)的字符。我的理解如Unicode字符集
null字符:一个所有位都为0的byte被称为null字符,用于标识字符串结尾。

4、环境限制
没有绝对的自由,无论是“翻译环境”还是“执行环境”都有一定的限制。
这里不想列举那么多的数字。
那我们该怎么得到这些限制呢?这里有几个头文件:
:int相关长度限制
:浮点数相关限制
:额外的一些关于int的限制。

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言精进之路1 Go语言精进之路2 商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats