重新拾起《C专家编程》,有了新的发现,此乃“温故而知新”啊!
先看了程序的内存的内存布局,再看前面数组与指针的不同,发现了之前对C字符串理解有些含糊,进步还是得点滴积累啊!
可执行程序的段结构及进程地址控件的截图如下:
这些段就不介绍啦,到处都是。下面写了代码测试一下,测试的过程中就想到了字符串:
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 char* p="we are in text segment"; //text in text segment 5 char globalArr[]="ds"; //text in data segment 6 int globalInt=6; //in data segment 7 int globalIntBSS; //in BSS 8 double globalDoubleBSS; //in BSS 9 char globalArrBSS[10]; //in BSS 10 11 int main(void) 12 { 13 char arr[]="we are in stack!"; //text is in stack 14 15 puts(" follows are in stack:"); 16 printf("%p ",arr); 17 printf("%p ",&arr[1]); 18 printf("%p ",&arr[2]); 19 //arr[1]='d'; 20 21 puts(" follows are in BSS:"); 22 printf("%p ",&globalIntBSS); 23 printf("%p ",&globalDoubleBSS); 24 25 strcpy(globalArrBSS,"lalala"); 26 printf("%s ",globalArrBSS); 27 printf("%d ",sizeof(globalArrBSS)); 28 printf("%p ",globalArrBSS); 29 printf("%p ",&globalArrBSS[1]); 30 31 puts(" follows are in data segment:"); 32 printf("%p ",&p); 33 printf("%p ",globalArr); 34 printf("%p ",&globalArr[1]); 35 printf("%p ",&globalArr[2]); 36 printf("%p ",&globalInt); 37 //globalArr[1]='a'; 38 39 puts(" follows are in text segment:"); 40 printf("%p ",p); 41 printf("%p ",&p[1]); 42 //p[4]='a'; 43 44 return 0; 45 }
程序结果如下:
可以看到从上到下的几个段的内存地址差别较大。
一:字符串在栈中
第13行 char arr[]="we are in stack!"; 定义的字符串在栈里面,这里arr标记了这个字符串的地址,第19行对它的某个字符进行更改是没有问题的,因为它的是栈里面的变量,可读可写。
二:字符串在BSS中
BSS段在目标文件也就是第一幅图 a.out 文件中只保存没有值的变量,目标文件中BSS段只要一个数值表示程序运行时在进程的地址空间中这个段的大小即可,程序真正运行是对应变量的。
第8行 double globalDoubleBSS; 只定义了一个变量而未赋值,所以就在BSS段了。同理第9行 char globalArrBSS[10]; 程序运行中用strcpy()给它赋值了,可以看到他们的地址是从0x601068开始的。
三:字符串在数据段中
第4行 char* p="we are in text segment"; p在数据段中,因为它是已经初始化了的变量,"we are in text segment" 是在文本段中。所以第42行对p[1]进行更改是不允许的。其实这句话的意思是:定义一个全局变量p,它是一个指针,指向放在文本段的字符串,因为p已经赋了初值了,所以它被放到了数据段。
第5行 char globalArr[]="ds"; 又不一样了,它是在数据段的数组,和上面不同,是因为 char* p 和 char p[] 是不一样的,这个这本书讲了,我不多说。所以第37行对数组进行更改是允许的。
四:字符串在文本段
第3行 char* p="we are in text segment"; 这句代码重述一下,有2点注意,1:p是放到了数据段的,因为p是经过初始化了的数据;2:"we are in text segment" 这个字符串是放到了文本段的,它是只读的了,所以如果第29行没注销的话,我的电脑编译通过了,但是运行是出现段错误,因为只读的不允许修改,如下:
这里有一个数组和指针并不相同的认识,《C专家编程》具体讲解了,详情见书,不多说。