首先,要寫這篇文章的緣由很是之慚愧,在看do_fork實現的源碼中,有以下(部分代碼省略):架構
do_fork:測試
struct task_struct *p;spa
p = alloc_task_struct();操作系統
*p = *current;指針
從代碼上看很清晰,聲明指針p,分配兩個物理頁內存,而後把當前進程的task_struct內容複製給p。原本都已經跳過了,但忽然想到歷來都是賦值地址,或者是strcpy的方式,尚未這樣寫過,而後打開編譯器試了一下,結果就牽扯出了一堆問題,不過如今搞清楚了。總結以下:code
版本1:blog
int main() { char *s = "abcdefg"; char *a = NULL; a = s; printf("%s\n", a); return 0; }
平時經常使用該方法,輸出結果:進程
abcdefg內存
版本2:字符串
int main() { char *s = "abcdefg"; char *a = malloc(sizeof(char) * 8); strcpy(a, s); printf("%s\n", a); return 0; }
平時經常使用該方法,輸出結果:
abcdefg。
版本2與版本1不一樣的地方在於,在2中爲a動態分配了8個字節內存(包含\0),而後strcpy將s指向的內存單元中的字符串拷貝到a指向的內存單元,若是不動態分配內存,則a指向非法地址,strcpy致使程序崩潰。
版本3:
主要是對某些理論進行了驗證。首先一個須要明確的概念爲,任何一種類型的指針變量只與系統架構有關,即32位操做系統爲4字節,64位操做系統爲8字節,代表能夠尋址的大小(固然這樣的說法不全對,還與編譯器等因素相關,但總之想代表與char *p, int *p的類型無關,這個概念差點都忘了)。先貼代碼:
int main() { char *s = "abcdefg";; printf("%p\n", &s); printf("%p\n", s); return 0; }
輸出結果:
%p顯示指針地址,與%#x相似。能夠看到指針s所在的內存單元,地址爲0x0060ff08,其保存了地址0x00403024(指針的本質)。
版本4:
以後我針對上述地址進行了測試。代碼以下:
int main() { char *s = "abcdefg";; printf("%p\n", &s); printf("%p\n", s); printf("%c\n", *s); printf("%s\n", 0x403024); printf("%s\n", 0x403025); printf("%c\n", *(char *)0x403026); return 0; }
輸出結果:
能夠看到c語言中的字符串,對於編譯器而言保存的爲地址,並且是字符串首字母的地址,咱們看到的是char *s = "abcdefg",實際上保存的爲 char *s = 0x403024 0x403025 ……,而char型的指針,指明瞭每一個元素佔用的內存大小爲一個字節,即24中保存a,25中保存b,若是爲int型指針,每一個元素佔用大小應該爲4個字節。
圖示爲:
並且在printf一個字符串時,字符串默認以\0結尾,因此在遇到\0是系統判斷字符串結束,因此若是上述代碼改成char *s = "abc\0defg",則打印結果爲abc。
最後補充一點,對於一個指針變量char *p, &p表示該變量自身的地址,p表示其保存的內容,*p表示將其內容做爲一個地址讀取其內容。若是其內容爲未分配內存的地址,則會致使系統崩潰。