聊聊指針
時(shí)間:2020-09-08 19:56:10
手機(jī)看文章
掃描二維碼
隨時(shí)隨地手機(jī)看文章
[導(dǎo)讀]指針是什么? 指針和其他的int, float等類(lèi)似, 是一種類(lèi)型. 有類(lèi)型就有相應(yīng)類(lèi)型的變量和常量. 本文主要討論變量的情況. 指針變量就是一種變量, 和其他種類(lèi)的變量類(lèi)似, 但指針和其他變量又有區(qū)別. 首先C語(yǔ)言作為一種類(lèi)型語(yǔ)言, 每個(gè)變量都會(huì)有幾個(gè)屬性. 變量名稱(chēng).
指針是什么?
指針和其他的int, float等類(lèi)似, 是一種類(lèi)型. 有類(lèi)型就有相應(yīng)類(lèi)型的變量和常量. 本文主要討論變量的情況.
指針變量就是一種變量, 和其他種類(lèi)的變量類(lèi)似, 但指針和其他變量又有區(qū)別.
首先C語(yǔ)言作為一種類(lèi)型語(yǔ)言, 每個(gè)變量都會(huì)有幾個(gè)屬性.
-
變量名稱(chēng). -
變量類(lèi)型. -
變量的值.
-
指針變量的名稱(chēng). -
指針變量的類(lèi)型, 即指針類(lèi)型. -
指針變量的值, 即一個(gè)地址. -
指針變量的值所指向的內(nèi)存里的數(shù)據(jù)類(lèi)型. 本文稱(chēng)做"指向類(lèi)型".
int a = 3; int *b = &a;
類(lèi)型
char * const * (*next)(), next是一個(gè)指針, 那么其指向類(lèi)型是什么? 這個(gè)聲明/定義比較復(fù)雜, 日常編程可能就會(huì)碰到比較 復(fù)雜的情況, 所以要搞清楚指針首先要懂得怎么看一個(gè)聲明/定義的變量的類(lèi)型.
<<c專(zhuān)家編程>>這本書(shū)中有一部分內(nèi)容專(zhuān)門(mén)講解怎么分析 一個(gè)變量的類(lèi)型, 值得參考.
-
從變量名稱(chēng)開(kāi)始讀取, 然后依照優(yōu)先級(jí)按順序處理. -
優(yōu)先級(jí)從高到低 a. 括號(hào)內(nèi)優(yōu)先級(jí)高. b. 后綴操作符, ()表示一個(gè)函數(shù), []表示一個(gè)數(shù)組. c. 前綴操作符, *表示"指向...的指針" -
如果const, volatile后面為類(lèi)型(int, long等), 那么作用于類(lèi)型, 其他情況下作用于const, volatile左邊的指針 *.
char * const * (*next)()
-
括號(hào)內(nèi)的優(yōu)先級(jí)最高, 即首先看 (*next) -
next左邊為 *, 因此next是一個(gè)指針類(lèi)型 -
然后后綴()的優(yōu)先級(jí)更高, 因此next是一個(gè)指針, 指向一個(gè)函數(shù). -
接著是const右邊的 *, 表示next是一個(gè)指針, 指向一個(gè)函數(shù), 該函數(shù)返回值類(lèi)型為一個(gè)指針. -
char * const看作一個(gè)整體為指向字符的常量指針.
<<c專(zhuān)家編程>>
類(lèi)型有什么用?
int a = 3, 那么在內(nèi)存中會(huì)存儲(chǔ)一個(gè)數(shù)據(jù)3, 那么對(duì)于int類(lèi)型具體來(lái)說(shuō).
-
這個(gè)數(shù)據(jù)3會(huì)占用4字節(jié)(常見(jiàn)32位機(jī)器與64位機(jī)器上int類(lèi)型占用4字節(jié)). 實(shí)際上是有4字節(jié)的內(nèi)存, 內(nèi)容是0×00000003. 因此int類(lèi)型就規(guī)定了占用的內(nèi)存大小. -
對(duì)于int類(lèi)型就可以進(jìn)行+,-,*,/等操作, 但是不能進(jìn)行取指針值(*a)的操作. 能夠進(jìn)行什么操作, 也是由類(lèi)型規(guī)定的.
sizeof
int *a;
double *b;
sizeof(a) == sizeof(b);
sizeof(*a) != sizeof(*b);
指針類(lèi)型的操作
+操作.
double a[3] = {1, 2, 3};
double *b = a;
printf("b: %p, content: %f\n", b, *b);
printf("b+1: %p, content: %f\n", b+1, *(b+1));
int c[3] = {1, 2, 3};
int *d = d;
printf("d: %p, content: %d\n", d, *d);
printf("d+1: %p, content: %d\n", d+1, *(d+1));
b: 0x7fff5f9ec7e0, content: 1.000000
b+1: 0x7fff5f9ec7e8, content: 2.000000
d: 0x7fff5f9ec7d0, content: 1
d+1: 0x7fff5f9ec7d4, content: 2
數(shù)組類(lèi)型
int a[10] = {0};
int *b = a;
int (*d)[10]= &a;
int c;
c = a[1];
c = b[1];
a[1]和
b[1]的區(qū)別就在于數(shù)組是一個(gè)常量, 而不是變量(變量本身需要占用內(nèi)存).
c = a[1]是直接從a表示的內(nèi)存地址偏移4字節(jié)的內(nèi)存中取數(shù)據(jù). 僅包含一次內(nèi)存讀操作.
c = b[1]是首先從內(nèi)存中取出變量b的值, 然后將變量b的值偏移4字節(jié), 然后從這個(gè)地址的內(nèi)存中取數(shù)據(jù). 包含2次內(nèi)存讀操作. 第一次是讀取變量b的值.
-
數(shù)組名稱(chēng)相當(dāng)于地址常量, 那么這個(gè)地址指向一段內(nèi)存, 因此這個(gè)地址本身會(huì)有指向類(lèi)型, 其指向類(lèi)型就是數(shù)組的元素類(lèi)型. 例如 int a[10], 那么a的指向類(lèi)型就是int, 因此a+1結(jié)果實(shí)際上指向a[1]. -
sizeof(a)是計(jì)算整個(gè)數(shù)組的類(lèi)型.sizeof(*a)是計(jì)算其指向類(lèi)型的大小.
-
可以對(duì)數(shù)組名進(jìn)行 &a操作(取地址), 實(shí)際上&a的指針值和a的指針值一樣, 而且也是個(gè)地址常量, 但是&a的指向類(lèi)型 是int [10], 即指向一個(gè)包含10個(gè)int元素的數(shù)組, 所以sizeof(*&a), 計(jì)算&a的指向類(lèi)型的占用內(nèi)存大小就是40. -
數(shù)組作為函數(shù)參數(shù)傳遞后, 在函數(shù)內(nèi)使用等價(jià)于指針. 因?yàn)楹瘮?shù)傳參是進(jìn)行值傳遞, 相當(dāng)于有一個(gè)指針變量記錄數(shù)組的地址值.
函數(shù)指針
int foo(int a)
{
return a;
}
int (*p_foo)(int a) = foo;
printf("%d, %d, %d\n", sizeof(foo), sizeof(*foo), sizeof(&foo));
printf("%d, %d\n", sizeof(p_foo), sizeof(*p_foo));
1, 1, 8
8, 1
-
對(duì)函數(shù)名本身計(jì)算類(lèi)型占用內(nèi)存大小, 其值為1, 對(duì)于函數(shù)名的指向類(lèi)型計(jì)算內(nèi)存占用大小其值也為1. -
foo, *foo, &foo的類(lèi)型相同, 但是sizeof(&foo)結(jié)果為8. -
函數(shù)指針可以進(jìn)行多次解引用, *****p_foo == *p_foo = p_foo. -
函數(shù)指針可以進(jìn)行調(diào)用, p_foo(3);
強(qiáng)制類(lèi)型轉(zhuǎn)換
double a = 23.456;
int *b = (int *) &a;
小結(jié)
-
指針名稱(chēng) -
指針類(lèi)型 -
指針內(nèi)容: 指向什么地方. -
指向類(lèi)型: 指向內(nèi)存的數(shù)據(jù)類(lèi)型是什么.
猜你喜歡
最 后
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!





