平臺: x86_64spa
GCC: 7.3指針
類型 | 長度 |
int | 4字節 |
int * | 8字節 |
有以下兩個文件:code
b.c:blog
#include <stdio.h> static int var = 0x5; int *func(void) { printf("var: %d, &var: %p\n", var, &var); return &var; }
a.c:ci
#include <stdio.h> int main(int argc, const char *argv[]) { int *ret = NULL; ret = func(); printf("*ret: %d\n", *ret); return 0; }
而後編譯運行:get
gcc a.c b.c ./a.out var: 5, &var: 0x55ac51c53010
Segmentation fault (core dumped)
能夠看到,在訪問返回的地址時發生了段錯誤,第一感受不該該啊,b.c裏定義的是static變量,並非局部變量啊。那麼咱們把返回的指針具體數值打印出來,看跟b.c中打印的是否一致,修改a.c以下:編譯器
#include <stdio.h> int main(int argc, const char *argv[]) { int *ret = NULL; ret = func(); printf("ret: %p\n", ret); return 0; }
運行以下:it
var: 5, &var: 0x56282a30b010 ret: 0x2a30b010
能夠看到,兩者果真不一樣,ret的值僅僅是&var的低4字節的內容。io
通過Google,發現,原來是沒有在a.c中對func()進行聲明,若是沒有對func聲明,GCC會默認認爲func返回的是int類型,而x86_64上,指針佔用8個字節,int類型僅僅佔用4個字節,因此在賦值時只會把&val的低4字節賦值給ret。編譯
能夠參考:
https://stackoverflow.com/questions/23144151/64-bit-function-returns-32-bit-pointer
修改以下,在a.c中增長對func的聲明,告訴編譯器func的返回值是一個指針類型,須要佔用8個字節長度
#include <stdio.h> extern int *func(void); int main(int argc, const char *argv[]) { int *ret = NULL; ret = func(); printf("ret: %p, *ret: %d\n", ret, *ret); return 0; }
輸出:
var: 5, &var: 0x561cb45bd010 ret: 0x561cb45bd010, *ret: 5
與此相似的還有一種:
.
├── a.c
├── b.c
├── common.h
common.h:
#ifndef __ABC_H__ #define __ABC_H__ struct ABC { int a; int b; int c; }; #endif
b.c:
#include "common.h" static struct ABC abc = { 1, 2, 3 }; struct ABC *func(void) { return &abc; }
a.c:
#include <stdio.h> extern struct ABC *func(void); int main(int argc, const char *argv[]) { int *ret = NULL; struct ABC *abc = func(); printf("abc: %p\n", abc); return 0; }
編譯運行:
gcc a.c b.c ./a.out abc: 0x55ed86710010
沒有問題,可是若是在a.c中去訪問結構體成員的話,編譯就會失敗:
gcc a.c b.c a.c: In function ‘main’: a.c:12:36: error: dereferencing pointer to incomplete type ‘struct ABC’ printf("a: %d, b: %d, c:%d\n", abc->a, abc->b, abc->c);
緣由是,在x86_64上,無論是什麼類型的指針,GCC都會會分配8個字節,這個不會有問題,可是若是要訪問指針指向的結構體成員的話,就須要告訴GCC這個成員具體是什麼樣子。解決辦法同時是須要聲明一下結構體類型,這裏包含對應的頭文件便可。
#include <stdio.h> #include "common.h" extern struct ABC *func(void); int main(int argc, const char *argv[]) { int *ret = NULL; struct ABC *abc = func(); printf("abc: %p\n", abc); printf("a: %d, b: %d, c:%d\n", abc->a, abc->b, abc->c); return 0; }
運行:
./a.out abc: 0x55f63c054010 a: 1, b: 2, c:3
完