指針(一)
在計算機科學中,指針(Pointer)是編程語言中的一個對象,利用地址,它的值直接指向(points to)存在電腦存儲器中另一個地方的值。由於通過地址能找到所需的變量單元,可以說,地址指向該變量單元。因此,將地址形象化的稱爲“指針”。意思是通過它能找到以它爲地址的內存單元。
——百度百科
運算符&取得變量的地址
· 獲得變量的地址,他的操作數必須是變量;
· int i ;printf("%x",&i);
int main(void)
{
int i = 0;
printf("0x%x\n", &i);
return 0;
}
運行結果,需要注意的是,取地址變量在每臺PC和每個編譯器的結果都是不一樣的,我們不必太過關注每次結果不同
0x62feac
老師視頻這裏解釋他編譯器這裏有報錯,上面的%x需要替換成%p,我用的Dev C++沒有報錯,這裏不再繼續探究,該地方跳過,如果報錯,記的選擇32位編譯
#include <stdio.h>
int main(void)
{
int i = 0;
int p;
p = &i; //報錯,需要(int)&強制轉換
// p = (int)&i; //報錯後,將&i 強制轉換爲int類型即可
printf("0x%x\n", &i);
printf("%p\n", &i);
return 0;
}
強制轉換後的運行結果,注意的是,這裏取出來的和老師取的值是不同的,不影響課程
0x62fea8
0062FEA8
上面在編譯器裏用32位架構編譯的結果,老師換成64位再編譯,會報錯,
“cast from ‘int*’ to ‘int’ loses precision ”
64位系統上指針類型佔用8個字節,而int類型佔用4個字節,所以會出現loses precision。
從這裏可以看出&可以給我們取出一個變量的地址,從而可以得出,我們需要printf輸出一個地址時,需要的是%p,地址和整數是不同的
· 地址的大小是否與int相同取決於編譯器
&不能取的地址
· &不能對沒有地址的東西去地址
· 如&(a+b)
· 如&(a++)
· 如&(++a)
下面來看一段上面例子的代碼
#include <stdio.h>
int main(void)
{
int i = 0;
int p;
p = (int)&i;
// p = (int)&(i+p);
// p = (int)&(i++);
// p = (int)&(++i);
printf("0x%x\n", &p);
printf("%p\n", &i);
return 0;
}
把上面三個註釋分別去掉,得出的報錯信息,三個報錯類型基本一致的,都是提示不能取這樣的值
D:\C\指針.cpp:8:16: error: lvalue required as unary ‘&’ operand p =
(int)&(i+p);
其他類型的&
· 變量的地址
· 相鄰的變量的地址
· &的結果的sizeof
· 數組的地址
· 數組單元的地址
· 相鄰的數組單元的地址
// 變量的地址
#include <stdio.h>
int main(void)
{
int i = 0;
int p;
printf("%p\n",&i); // 變量的地址
printf("%p\n", &p); // 相鄰變量的地址
printf("%p\n",sizeof(int)); // sizeof(int)地址
return 0;
}
執行結果
0061FEAC
0061FEA8
00000004
C在16進制代表的是12,從這裏可以看出AC和A8中間差了4位,從上面得知int佔據的是4個字節,因此他們是相鄰的內存地址,在堆棧裏自頂向下分配的,他們的差距是4,剛好等於sizeof(int)
// 數組的地址
#include <stdio.h>
int main(void)
{
int a[10];
printf("&a=%p\n",&a); // a交給取地址符
printf("a=%p\n", a); // a直接當一個地址
printf("a[0]=%p\n",&a[0]); // 獲取a[0]的地址
printf("a[1]=%p\n",&a[1]); // 獲取a[1]的地址
return 0;
}
執行結果,從這裏可以看出相鄰單元的數組差距,永遠是4
&a =0061FE88
a =0061FE88
a[0] =0061FE88
a[1] =0061FE8C