在用C语言编程时,一直有个疑惑:
char *a = "abc";
char b[4] = "abc";
这两句在C语言中有什么不同吗?
按理来说,a和b都是局部变量,只不过一个是指针,一个是数组。有人说,两个的长度不一样,从C风格的字符串来说是的,第一个长度为3,第二个的长度为4,其实也可以将第二个的长度改为3,只不过打印时就不太好看了。
其实,更深层次的问题是,当程序运行时,对于这两行代码,"abc"出现在哪儿?
1 常量字符串去哪儿了
运行下面一个简单的程序:
#include
int main()
{
char *a = "abc";
char b[4] = "abc";
printf("char* address : %p\t a address : %p\n", a, &a);
printf("array address : %p\t b address : %p\n", b, &b);
while(1) ;
return 0;
}
上面的代码分别定义了一个char*变量和一个char型数组,然后分别打印它们的地址。
最后一个while循环是为了不让程序结束,以便查看程序运行时的数据存放的位置。
将以上代码编译运行后:
程序已经打印出了两个字符串的地址以及a和b的地址,然后在一个新的terminal中执行下面的命令:
首先输入ps -aux | grep a.out在查看a.out的进程ID,然后用cat命令查看该进程的各个段的地址。
08048000-08049000 r-xp 代码段
08049000-0804a000 r--p 没看到有这个地址的数据
0804a000-0804b000 rw-p 数据段
bff35000-bff56000 rw-p 栈
由于程序中没有进行动态内存分配,因此没有显示堆。
将上面的地址与程序运行打印的结果进行对比:
对于char *a = "abc","abc"与代码段存放在一起,在栈中分配了一个指针,它的值就是"abc"的地址。
对于char b[4] = "abc","abc"存放在栈中,变量b的值等于"abc"在栈中的地址,可以假想成b是一个符号,它对应"abc"的首地址。
2 linux中C程序运行时数据的分布
用上面类似的方法处理下面的程序:
#include
int g_init = 1;
int g_uinit;
static int s_g_init = 1;
static int s_g_uinit;
const int c_g = 1;
int main()
{
int l_init = 1;
int l_uinit;
static int s_l_init = 1;
static int s_l_uinit;
const int c_l = 1;
printf(" global init : %p\n", &g_init);
printf(" global uninit : %p\n", &g_uinit);
printf(" static global init : %p\n", &s_g_init);
printf("static global uninit : %p\n", &s_g_uinit);
printf(" const global : %p\n\n", &c_g);
printf(" local init : %p\n", &l_init);
printf(" local uninit : %p\n", &l_uinit);
printf(" static local init : %p\n", &s_l_init);
printf(" static local uninit : %p\n", &s_l_uinit);
printf(" const local : %p\n", &c_l);
while(1) ;
return 0;
}
上面的数据分为三个部分:
以0x8048为页框地址:全局的const变量,它的地址在代码段中,因为这种变量在编译之后就会替换代码中的值,跟define常量一样。
以0x804a为页框地址:全局的静态变量和非静态变量,局部的静态变量。
以0xbfd50为页框地址:局部变量和局部const变量。
也就是说,对于程序中的变量,只有局部的非静态变量在栈中,全局的const变量已经嵌入代码中,其它类型的数据都放在数据段中。
而对于字符串来说,当定义char *时,实际应该是const char *,它的内容放在代码段中,而指针遍历遵循一般的const规则。
而且,从上面的初始化变量和非初始化变量的地址大小可以看到,初始化变量和非初始化变量确实是分开存放的。
要注意的是,这里说的是linux下的C程序,其它系统下可能不太一样。
参考资料:
http://blog.chinaunix.net/uid-26548237-id-3818734.html
http://blog.csdn.net/embedded_hunter/article/details/6897027