重新拾起《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("\nfollows are in stack:"); 16 printf("%p\n",arr); 17 printf("%p\n",&arr[1]); 18 printf("%p\n",&arr[2]); 19 //arr[1]='d'; 20 21 puts("\nfollows are in BSS:"); 22 printf("%p\n",&globalIntBSS); 23 printf("%p\n",&globalDoubleBSS); 24 25 strcpy(globalArrBSS,"lalala"); 26 printf("%s\n",globalArrBSS); 27 printf("%d\n",sizeof(globalArrBSS)); 28 printf("%p\n",globalArrBSS); 29 printf("%p\n",&globalArrBSS[1]); 30 31 puts("\nfollows are in data segment:"); 32 printf("%p\n",&p); 33 printf("%p\n",globalArr); 34 printf("%p\n",&globalArr[1]); 35 printf("%p\n",&globalArr[2]); 36 printf("%p\n",&globalInt); 37 //globalArr[1]='a'; 38 39 puts("\nfollows are in text segment:"); 40 printf("%p\n",p); 41 printf("%p\n",&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專家編程》具體講解了,詳情見書,不多說。