本篇文章是從 指針的運(yùn)算開(kāi)始講的 螃成,可能對(duì)完全沒(méi)基礎(chǔ)的同學(xué)不太友好
建議從這一篇文章開(kāi)始閱讀
指針的運(yùn)算 詳解 [C語(yǔ)言必知必會(huì)]
指針的運(yùn)算
指針加減 常量
請(qǐng)看下面的程序祷嘶,猜測(cè)一下結(jié)果:
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);
}
運(yùn)行結(jié)果:
a = 00AFF82C
a + 1 = 00AFF830
a - 1 = 00AFF828
可以看到锭亏, a 與 a + 1 和 a - 1 都差了四個(gè)字節(jié)
指針加減常量 加減的大小為
sizeof(類(lèi)型) * 常量
再試試 char 類(lèi)型杈绸?
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);
}
結(jié)果如我們所料:
a = 0095F9E0
a + 1 = 0095F9E1
a - 1 = 0095F9DF
相差大小 為 1
指針 - 指針
先來(lái)看一段程序吧:
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);
}
指針相減 結(jié)果會(huì)是 指針相差的大小嗎?看結(jié)果:
ch1 - ch2 = 4
ch2 - ch1 = -4
i1 - i2 = 4
i2 - i1 = -4
指針 減 指針 意義是 兩個(gè)地址之間相隔的單元格數(shù)
也可以理解為:指針相差的大小 / sizeof(類(lèi)型)
如果想輸出兩個(gè)指針 相差的距離(大械乖础)只需要將變量類(lèi)型 更改成普通類(lèi)型隶症,如下:
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);
}
輸出結(jié)果:
ch1 - ch2 = 4
ch2 - ch1 = -4
i1 - i2 = 16
i2 - i1 = -16
普通類(lèi)型是無(wú)法進(jìn)行解引用操作的
總結(jié)一下
指針 可以 加減常數(shù),指針之間可以相減呐粘,可以比較(如:> == < >=等)
但是指針不能乘除满俗,相加 這是沒(méi)有意義的
舉個(gè)很簡(jiǎn)單的例子,時(shí)間可以相減事哭,但是時(shí)間乘除或者相加有什么意義呢漫雷?
NULL
通過(guò)前面的學(xué)習(xí)瓜富,我們知道:內(nèi)存中的地址有很多編號(hào)鳍咱。如果你的機(jī)器是 32 位,
那么內(nèi)存范圍是:0 ~ 2^32 -1
(32位2進(jìn)制數(shù)全1) 最大值大約為 4GB
NULL其實(shí)就表示 0地址
補(bǔ)充個(gè)小知識(shí)點(diǎn):
1kB=1024B =2^10(次方是二進(jìn)制形式)
1MB=1024kB =2^20
1GB=1024MB =2^30
1TB=1024GB =2^40
NULL有什么用?
0地址規(guī)定為我們不能寫(xiě)入的地址,你的指針不指向 0地址织中,如果你的指針指向了 0地址 那么程序運(yùn)行時(shí)會(huì)崩潰抗悍。基于這個(gè)特點(diǎn)串述,0地址 也就是NULL有了很重要的功能:
- 函數(shù)返回 NULL指示錯(cuò)誤
- 防止野指針(什么是野指針?參考 C語(yǔ)言復(fù)習(xí)鞏固(五) 指針(初階))。用NULL初始化指針脯倚,如果指針使用時(shí)沒(méi)有指向任何實(shí)際地址,程序崩潰嵌屎。
NULL類(lèi)型時(shí) void * 可以設(shè)置任何類(lèi)型為NULL
下面的程序是官網(wǎng)上講NULL時(shí)給出的例子:
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
// 能設(shè)置任何類(lèi)型指針為 NULL
int* p = NULL;
struct S* s = NULL;
void(*f)(int, double) = NULL;
// 多數(shù)返回指針的函數(shù)用空指針指示錯(cuò)誤
char* ptr = malloc(10);
if (ptr == NULL) printf("Out of memory");
free(ptr);
}
void*
void* 表示 不知道指向什么類(lèi)型的 指針
比如:
int i = 1;
int* p = &i;
void* q = (void*)p;
這么寫(xiě)并沒(méi)有改變 p 所指向的變量的類(lèi)型推正, 而是可以讓程序用不同的眼光通過(guò) p看它所指的變量。
指針類(lèi)型的作用
1. 指針的類(lèi)型決定了指針向前或者向后走一步有多大
2. 指針的類(lèi)型決定了宝惰,對(duì)指針解引用的時(shí)候有多大的權(quán)限(能操作幾個(gè)字節(jié))
(具體示例參考 C語(yǔ)言復(fù)習(xí)鞏固(五) 指針(初階))
更多關(guān)于指針的可以參考我的其他篇文章: