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