C语言的作用域/namespace分析

C语言的作用域/namespace分析

[dave_cn.20091111]

转载请注明出处。http://www.cnblogs.com/dave_cn/

 

在csdn上看到一段代码。觉得很有意思,于是便自己动动手分析分析。 

这是用于分析C语言中的作用的一段代码,值得研究研究。 

代码中calloc之后并没有free掉,这是个不好的习惯. :)

好吧,我们从代码开始: 

 

原始代码

 1 #include <stdio.h>
2 #include <stdlib.h>
3
4 int x(const int int_a) {return int_a;}
5
6 struct x
7 {
8 int x;
9 };
10
11 #define x(x) x
12
13 int main(int argc, char *argv[])
14 {
15 int *x = calloc(1, sizeof x);
16
17 x: (((struct x *)x)->x) = x(5);
18
19 printf("%p\n", ((struct x *)x)->x);
20
21 return 0;
22 }
23 /*
24 output:
25 0x5
26 */


[0] 变量名(包括指针名,函数名)和自定义类型名(struct)存在于不同namespace.所以b不会和a,c冲突
 1 int x(const int int_a) {return int_a;}      //a
2
3 struct x //b
4 {
5 int x;
6 };
7
8 #define x(x) x
9
10 int main(int argc, char *argv[])
11 {
12 int *x = calloc(1, sizeof x); //c
13
14 x: (((struct x *)x)->x) = x(5);
15
16 printf("%p\n", ((struct x *)x)->x);
17
18 return 0;
19 }

[1] (int *)x和(int *(const int))x不在同一层namespace,编译通过.
 链接时出错.(int *)x将(int *(const int))x覆盖,所以在c行时会找不到匹配的函数名
 1 int x(const int int_a) {return int_a;}   //a
2
3 struct x
4 {
5 int x;
6 };
7
8 //#define x(x) x
9
10 int main(int argc, char *argv[])
11 {
12 int *x = calloc(1, sizeof x); //b
13
14 x: (((struct x *)x)->x) = x(5); //c
15
16 printf("%p\n", ((struct x *)x)->x);
17
18 return 0;
19 }

[2] 编译通过
 1 int x(const int int_a) {return int_a;}
2
3 struct x
4 {
5 int x;
6 };
7
8 //#define x(x) x
9
10 int main(int argc, char *argv[])
11 {
12 int *x = calloc(1, sizeof x);
13
14 //x: (((struct x *)x)->x) = x(5);
15
16 //printf("%p\n", ((struct x *)x)->x);
17
18 return 0;
19 }

[3] 编译出错.(int *)x和(int *(const int))x在同一层namespace,冲突.

 

1 int x(const int int_a) {return int_a;}
2
3 int *x;
4
5 int main(int argc, char *argv[])
6 {
7 return 0;
8 }


[4] #define在预编译阶段替换其后面代码,所以对#define后面的代码来说,x(n)被替换为n,所以在编译时代码会扩展为如下:
 1 int x(const int int_a) {return int_a;}
2
3 struct x
4 {
5 int x;
6 };
7
8 #define x(x) x
9
10 int main(int argc, char *argv[])
11 {
12 int *x = calloc(1, sizeof x);
13
14 x: (((struct x *)x)->x) = 5; //x(5)替换为5,所以并没有调用函数int x(const int)
15
16 printf("%p\n", ((struct x *)x)->x);
17
18 return 0;
19 }

关于标签label.
标签,仅仅是一个符号,存在一个label专用的namespace,仅对goto可见,所以不会与变量或者常量冲突.
在MSDN的goto条目中也有相关的描述:
"The set of identifier names following a goto has its own name space so the names do not interfere with other identifiers. Labels cannot be redeclared."
 1 int main(int argc, char *argv[])
2 {
3 int p = 5;
4
5 x: printf("line x.\n");
6
7 ++p;
8
9 if (p == 8) return 0;
10
11 goto x;
12 }
13
14 int main(int argc, char *argv[])
15 {
16 int x = 5;
17
18 x: printf("label x.\n"); //这里的label x与(int)x是无关的
19
20 ++x;
21
22 if (x == 8) return 0;
23
24 goto x; //goto会在标签namespace查找label x.
25
26 printf("x = %d | :( .\n", x); //无效语句
27 return 0; //无效语句
28 }

[5] 所以代码中label x与其他命名不冲突
 1 int x(const int int_a) {return int_a;}
2
3 struct x
4 {
5 int x;
6 };
7
8 #define x(x) x
9
10 int main(int argc, char *argv[])
11 {
12 int *x = calloc(1, sizeof x);
13
14 x: (((struct x *)x)->x) = x(5); //这里的label x存在于独立的namespace,与其他不冲突.
15
16 printf("%p\n", ((struct x *)x)->x);
17
18 return 0;
19 }

[6] 现在我们把代码中无效代码去掉,并把宏定义语句手动替换掉,是的代码简洁点
 1 struct x
2 {
3 int x;
4 };
5
6 int main(int argc, char *argv[])
7 {
8 int *x = calloc(1, sizeof(int *));
9
10 //到此我们有自定义类型struct x和变量(int *)x,其中struct x作用域为全局,(int *)x作用域为main()
11
12 (((struct x *)x)->x) = 5;
13 //
14 // 这里的x是由(int *)强制转化成(struct x *),所以后面实际是给struct中的(int)x赋值
15
16 printf("%p\n", ((struct x *)x)->x); //这里还是需要强制转化成struct,这样才能识别,然后得到(int)x的值
17
18 return 0;
19 }

到此代码中所有的x都说明了,这里再次总结下.
 1 #include <stdio.h>
2 #include <stdlib.h>
3
4 int x(const int int_a) {return int_a;} //全局的函数名
5
6 struct x //全局的struct名,属于自定义类型名,所以不会跟上面的(int *(const int))x及下面main中的(int *)x冲突{
7 int x; //属于struct x的int型x
8 };
9
10 #define x(x) x //宏定义,会在预编译时进行代码扩展,所以并不会在编译时产生命名冲突
11
12 int main(int argc, char *argv[])
13 {
14 int *x = calloc(1, sizeof x); //作用域为main的(int *)x; sizeof计算的是(int *)x大小.
15
16 x: (((struct x *)x)->x) = x(5); //作为label的x独立存在于一个namespace.
17
18 printf("%p\n", ((struct x *)x)->x);
19
20 return 0;
21 }


posted @ 2009-11-12 00:05  mr. dave  阅读(2811)  评论(4编辑  收藏  举报