關於指針

首先,要寫這篇文章的緣由很是之慚愧,在看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表示將其內容做爲一個地址讀取其內容。若是其內容爲未分配內存的地址,則會致使系統崩潰。

相關文章
相關標籤/搜索