指針的運算 詳解 [C語言必知必會]
指針的運算
指針加減 常量
請看下面的程序,猜測一下結果:
<code>int main() {
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int* a = &arr;
printf("a = %p\\n", a);
printf("a + 1 = %p\\n", a + 1);
printf("a - 1 = %p\\n", a - 1);
}
/<code>
運行結果:
<code>a = 00AFF82C
a + 1 = 00AFF830
a - 1 = 00AFF828
/<code>
可以看到, a 與 a + 1 和 a - 1 都差了四個字節
指針加減常量 加減的大小為 sizeof(類型) * 常量
再試試 char 類型?
<code>int main() {
char arr[10] = { ' 1', '2', '3', '4', '5', '6', '7', '8', '9', '10',};
char* a = &arr;
printf("a = %p\\n", a);
printf("a + 1 = %p\\n", a + 1);
printf("a - 1 = %p\\n", a - 1);
}
/<code>
結果如我們所料:
<code>a = 0095F9E0
a + 1 = 0095F9E1
a - 1 = 0095F9DF
/<code>
相差大小 為 1
指針 - 指針
先來看一段程序吧:
<code>int main() {
char arr1[10] = { ' 1', '2', '3', '4', '5', '6', '7', '8', '9', '10', };
int arr2[5] = { 1, 2, 3, 4, 5 };
char* ch1 = &arr1[4];
char* ch2 = &arr1;
int* i1 = &arr2[4];
int* i2 = &arr2;
printf("ch1 - ch2 = %d\\n", ch1 - ch2);
printf("ch2 - ch1 = %d\\n", ch2 - ch1);
printf("\\ni1 - i2 = %d\\n", i1 - i2);
printf("i2 - i1 = %d\\n", i2 - i1);
}
/<code>
指針相減 結果會是 指針相差的大小嗎?看結果:
<code>ch1 - ch2 = 4
ch2 - ch1 = -4
i1 - i2 = 4
i2 - i1 = -4
/<code>
指針 減 指針 意義是 兩個地址之間相隔的單元格數也可以理解為:指針相差的大小 / sizeof(類型)
如果想輸出兩個指針 相差的距離(大小)只需要將變量類型 更改成普通類型,如下:
<code>int main() {
char arr1[10] = { ' 1', '2', '3', '4', '5', '6', '7', '8', '9', '10', };
int arr2[5] = { 1, 2, 3, 4, 5 };
//變量不再是指針變量
char ch1 = &arr1[4];
char ch2 = &arr1;
int i1 = &arr2[4];
int i2 = &arr2;
printf("ch1 - ch2 = %d\\n", ch1 - ch2);
printf("ch2 - ch1 = %d\\n", ch2 - ch1);
printf("\\n");
printf("i1 - i2 = %d\\n", i1 - i2);
printf("i2 - i1 = %d\\n", i2 - i1);
}
/<code>
輸出結果:
<code>ch1 - ch2 = 4
ch2 - ch1 = -4
i1 - i2 = 16
i2 - i1 = -16
/<code>
普通類型是無法進行解引用操作的
總結一下
指針 可以 加減常數,指針之間可以相減,可以比較(如:> == < >=等)但是指針不能乘除,相加 這是沒有意義的舉個很簡單的例子,時間可以相減,但是時間乘除或者相加有什麼意義呢?
NULL
通過前面的學習,我們知道:內存中的地址有很多編號。如果你的機器是 32 位,那麼內存範圍是:0 ~ 2^32 -1(32位2進制數全1) 最大值大約為 4GBNULL其實就表示 0地址補充個小知識點:1kB=1024B =2^10(次方是二進制形式)1MB=1024kB =2^201GB=1024MB =2^301TB=1024GB =2^40
NULL有什麼用?
0地址規定為我們不能寫入的地址,你的指針不指向 0地址,如果你的指針指向了 0地址 那麼程序運行時會崩潰。基於這個特點,0地址 也就是NULL有了很重要的功能:
- 函數返回 NULL指示錯誤
- 防止野指針。用NULL初始化指針,如果指針使用時沒有指向任何實際地址,程序崩潰。
NULL類型時 void * 可以設置任何類型為NULL下面的程序是官網上講NULL時給出的例子:
<code>#include <stdlib.h>
#include <stdio.h>
int main(void)
{
// 能設置任何類型指針為 NULL
int* p = NULL;
struct S* s = NULL;
void(*f)(int, double) = NULL;
// 多數返回指針的函數用空指針指示錯誤
char* ptr = malloc(10);
if (ptr == NULL) printf("Out of memory");
free(ptr);
}
/<stdio.h>/<stdlib.h>/<code>
void*
void* 表示 不知道指向什麼類型的 指針比如:
<code>int i = 1;
int* p = &i;
void* q = (void*)p;
/<code>
這麼寫並沒有改變 p 所指向的變量的類型, 而是可以讓程序用不同的眼光通過 p看它所指的變量。
指針類型的作用
1. 指針的類型決定了指針向前或者向後走一步有多大
2. 指針的類型決定了,對指針解引用的時候有多大的權限(能操作幾個字節)
閱讀更多 編程反思錄 的文章