该楼层疑似违规已被系统折叠 隐藏此楼查看此楼
大家好,其实类似的帖子我发过,是动员大家一起翻译标准C文档的,加入的人并不多,就我们3.4个,但这并不能打消LZ对标准的热爱。LZ已经看完了许多部分,且翻译了数个章节,还在继续中。在这里顺便打个小广告,鼓舞大家一起加入到标准c的翻译工作中。301834378这是群号。
有人说为什么要追求标准?这我就不回答了。仁者见仁,智者见智的事情。
这系列贴子主要面向那些中级C程序员,如果你连C的基础语法都没掌握好,看这个没什么意义。
本人能力也有限,但一定尽最大的努力写出自己对标准的理解。有错误之处请大家指出,并和我讨论~
1. 标识符的作用域
先来看看标准对标识符的定义:
For each different entity that an identifier designates, the identifier is visible(i.e., can be used) only within a region of program text called its scope.
翻译过来就是:
对于标识符表示的每个不同的实体来说,该标识符可见 (即可使用)的程序文本的范围称为它的作用域。
相信大家对标识符的作用域这个顾名思义概念并不陌生。标准将作用域分为四种:
文件作用域 file scope
函数作用域 function scope
块作用域 block scope
函数原型作用域 function proto scope
再来看定义(这里我直接上我翻译的,我会简化地发上来):
如果标识符声明在任何块和参数列表之外,此标识符就为文件作用域。
如果标识符声明在任何块和函数定义时的参数列表之外,此标识符就为块作用域。
如果标识符声明在(并非函数定义时的)函数原型的参数列表中,此标识符就为函数原型作用域。
首先,说明一个概念,函数原型,简单的说就是声明了参数类型的函数声明,比如这样:
double foo(void),int foo(char, float);
而:
int bar(); 或 void bar(arg1, arg2);
就不是原型声明,因为它们没有声明参数类型。
(注:int bar(); 或 void bar(arg1, arg2); 都是旧式C函数声明)
唉?为什么没有函数作用域的定义?是的,标准中这样概括函数作用域:
标号名是唯一一种具有函数作用域的标识符。
没错,只有标号名为函数作用域。
这样,我们可以来判断一些标识符的作用域了:
int fs_i1;
typedef short int fs_i2;
struct fs_i3;
void fs_i4(int ps_arg1, long ps_arg2);
int main(int argc; char *argv[])
{
int bs_i1;
struct bs_i2
{
int bs_i3;
};
/* .. */
JUST_DO_IT:
goto JUST_DO_IT;
}
这个代码片段涵盖了所有作用域。现在我们来分析。
fs_i1、fs_i2、fs_i3、fs_i4以及我们亲爱的main它们都是标识符,分别代表一个对象(变量)、类型名(short int的别名)、结构名,后两个为函数名,它们都未在任何块和参数列表之内,因此,是文件作用域。
现在来看ps_arg1, ps_arg2和argc,argv,如果你不仔细看前面的话,你会认为它们都是函数原型作用域。但是,错,后两者不是,至于正确答案你可以回头看看前面的定义。(其实这符合我们所使用的——你总是可以在函数体中引用参数)
JUST_DO_IT这个标号不用说,唯一具有函数作用域的标识符。
bs_i1, bs_i2它们声明在函数体这个块里,因此,为块作用域。(很多同学都会认为声明在函数体里的标识符就是函数作用域,其实不然,它们只是块作用域)
等等?bs_i3是什么??我仿佛根据上面的定义找不到它的作用与。正确答案是——它也是块作用域。什么?为什么?
标准上有这样一段话:
Every other identifier has scope determined by the placement of its declaration (in a declarator or type specifier).
其他(指除标号名以外的)任何一个标识符的作用域都由其声明(位于声明符或类型说明符中)所在的位置决定。
靠!什么是声明符,什么是类型说明符?这里牵扯到以后的概念,但你现在只用知道
struct bs_i2
{
int bs_i3;
}
这玩意就是一个类型说明符。
char *argv[];中,*argv[]就是声明符,char就是类型说明符。
因此,我们说,bs_i3所在的类型说明符是块作用域,所以它也是。
OK,作用域就说到这里。稍后看下一个概念,标识符的命名空间。(先说好,以为是C++中的namespace的去面壁,人家是name space)