Loading... # pointers-in-c-language > 關於 c 語言中的指針 `*` 以及 `&` 的個人理解 首先需要理解先驗知識: 1. `format ‘%p’ expects argument of type ‘void *’`,即 `printf("%p", (void *)x);`,這個 `printf` 函數中,使用格式化 `%p` 時,傳給其的參數應爲一個 `(void *)`,即指針類型的變量 2. 可以簡單地先將 `*` 理解爲向目標裏取,`&` 為向目標外取,這麽說可能比較抽象,如下圖所示: ![圖 1](https://tataramoriko-oss.oss-cn-shenzhen.aliyuncs.com/markdown/image-20230601154617669.png) 1. 對於一個變量 `x`;稱 `x` 為變量本身,`*x` 為變量裏的内容,`&x` 為變量外的内容(也就是其地址,而 `&` 也被稱之爲取址符) 2. 此時如果取 `*x` 可以得到 `0x7ffabcde08`;此時如果取 `&x` 可以得到 `0x7ffabcde04`,也就是 `x` 的地址; 3. 在這裏使 `int **y = &x`,當使用 `*y` 時,會返回 `0x7ffabcde04`;取 `**y`,則其取得鏈應為:`**y = *(&x) = *x = 0x7ffabcde08`,這裏可能會好奇其中的 `*(&x) = *x` 爲什麽會成立,這是因爲回顧 `*` 和 `&` 所代表的意思,`*(&x)` 的意思就是 **取 x 的地址**,**然後 `*` 這個地址**,這與 `*x` 最後得出的值是一樣的 4. 在指針這塊不能簡單地用直觀地數學等式來計算,而應該關注其實際代表的意義 然後來編寫以下源碼内容 `pointers.c`: ```c # include <stdio.h> # include <stdlib.h> int a = 10; int *x = &a; int **y = &x; int main() { printf("a = %d \n", a); printf("&a = %p \n\n", &a); printf("x = %p \n", x); printf("*x = %d \n", *x); printf("&x = %p \n\n", &x); printf("y = %p \n", y); printf("*y = %p \n", *y); printf("&y = %p \n\n", &y); getchar(); return 0; } ``` 使用 `gcc -o pointers -m32 pointers.c` 來編譯生成可執行文件 如圖所示,圖中左邊是運行結果,右邊是使用 gdb 查看運行時的内存中的内容,*這裏由於定義時使用的是全域變量,故相應的值會在 `.data` 段中,在 stack 上也同理,此處只是爲了方便理解指針的概念* ![圖 2](https://tataramoriko-oss.oss-cn-shenzhen.aliyuncs.com/markdown/image-20230601142720318.png) 以下是幾個幫助理解的 tips 1. 使用 `int a = 10` 時定義了一個 `int` 類型的變量,名稱為 a,在編譯時會被放入到 elf 的 `.data` 段位置 `0x565d3008`,當然這裏使用了一個實際裝載的地址,在不同機器上出現的都不一樣,此處是爲了結合圖片更好理解(下同) 2. 使用 `int *x = &a`,可以很直觀地理解到,定義了一個 `int *` 類型的指針變量 x,并給其賦值為 `&a`,即 a 的地址 `0x565d3008`,并且該 x 在 `.data` 中的位置為 `0x565d300c`;并且可以直觀地發現如下事實 1. 位置 `0x565d300c` 処,即是用 `int *x` 聲明的該變量 x,其值是參數 a 的地址 2. 當使用 `*x` 時,相當於取了 `0x565d300c` 這個位置上的值(由於該位置上的值為一個地址,使用格式化 `%d` 時,就會把這個地址上的數字打印出來) 3. 當使用 `&x` 時,相當於取了 `0x565d300c` 這個位置的地址 3. 使用 `int **y = &x`,其原理與上述第 2 點差不多,不再贅述 根據前文的内容,其實可以用一個比較好記憶的方式來理解指針的使用: 1. 當定義一個變量時,請將其看作一行内容,如上圖右邊 gdb 中的内容所示: | 地址(即 `&x`) | 注釋(方便理解,實際不存在,即 `x`) | 内容(即 `*x`) | | --------------- | ------------------------------------ | --------------- | | 0x565d3008 | `int a = 10` 中的 `a` | 0xa | | 0x565d300c | `int *x = &a` 中的 `x` | 0x565d3008 | | 0x565d3010 | `int **y = &x` 中的 `y` | 0x565d300c | 2. 一行内容其實只有兩個值,即 **地址 : 内容** 3. 當我們在程序中使用到一個變量 `x` 時,其實相當於取到了 `x` 對應的這行内容,使用 `*x` 就可以獲得這行的值,使用 `&x` 就可以獲得這行的地址 4. `int *x = &a` 的意思可以更明確一點;即定義了一個 `int *` 類型的變量,這個變量的名字是 `x`,其中存放的是一個 `int` 類型的變量的**地址** 5. `int **y = &x`,定義了一個 `int **` 類型的變量,這個變量的名字是 `y`,其中存放的是一個 `int *` 類型的變量的**地址** © 允许规范转载 赞 如果觉得我的文章对你有用,请随意赞赏