最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

賭你會(huì)懵的C語言指針進(jìn)階數(shù)組場景解析

 更新時(shí)間:2022年02月14日 10:47:47   作者:喬喬家的龍龍  
這篇文章主要為大家介紹了關(guān)于C語言指針進(jìn)階的示例解析,來細(xì)化指針這一部分內(nèi)容,現(xiàn)在著重把一些指針的運(yùn)用情景搬出來康康,如果對(duì)指針盤的不是非常熟練,或者指針還出于入門階段的鐵子請(qǐng)繞道

正片開始

細(xì)化指針這一部分內(nèi)容,現(xiàn)在著重把一些指針的運(yùn)用情景搬出來康康,如果對(duì)指針盤的不是非常熟練,或者指針還出于入門階段的鐵子請(qǐng)繞道(暈頭警告)

直接給大家盤個(gè)套餐:

一維數(shù)組

int a[] = {1,2,3,4,5};
printf("%d\n",sizeof(a));
printf("%d\n",sizeof(a+0));
printf("%d\n",sizeof(*a));
printf("%d\n",sizeof(a+1));
printf("%d\n",sizeof(a[1]));
printf("%d\n",sizeof(&a));
printf("%d\n",sizeof(*&a));
printf("%d\n",sizeof(&a+1));
printf("%d\n",sizeof(&a[0]));
printf("%d\n",sizeof(&a[0]+1));

問題很簡單,這組 printf 的值是多少?小朋友你是否有些許害怕,但是沒有關(guān)系我們逐個(gè)擊破,這是后續(xù)內(nèi)容的基礎(chǔ)

記住你的答案,來看看編譯器是怎么解析的:

在這里插入圖片描述

首先我們應(yīng)該知道數(shù)組名代表的是數(shù)組首元素的地址,但是要知道我們有兩種例外:

1.sizeof (),()內(nèi)是數(shù)組名時(shí),代表的就是整個(gè)數(shù)組,計(jì)算的就是數(shù)組的大小,單位是字節(jié);

2. & 數(shù)組名時(shí),表示的也是整個(gè)數(shù)組,取出的就是整個(gè)數(shù)組地址;

除了以上兩種情況,其余的所有數(shù)組名都表示首元素地址!

所以

1.sizeof(a)就是直接將數(shù)組名放進(jìn)去,算出的就應(yīng)該是 sizeof(int)*5 = 20

2.sizeof(a+0)此時(shí)不只有數(shù)組名,因此 a 代表首元素地址,a+0 等價(jià)于 a,是地址大小,在32位/64位平臺(tái)下對(duì)應(yīng) 4/8 字節(jié)大小

3.*a ,不只有數(shù)組名 a 代表首元素地址,解引用得到首元素,sizeof(a)= sizeof(int)= 4

4.a+1 老規(guī)矩還是首元素地址+1,就是第二個(gè)元素地址,是地址大小為 4/8 字節(jié)

5.a[ 1 ],大小為4

6.&a 為整個(gè)數(shù)組地址,但是地址終歸是 4/8 字節(jié)

7. * &a ,&a 是類型為 int()[4] 的數(shù)組指針,解引用數(shù)組地址為整個(gè)數(shù)組,大小 20

8. &a +1取出整個(gè)數(shù)組地址,一個(gè)數(shù)組指針的單位就是整個(gè)數(shù)組,+1 就會(huì)跳過整個(gè)數(shù)組,大小還是為第二個(gè)數(shù)組地址,大小 4/8

9. &a[0],首元素地址,4/8

10. &a[0] + 1,第二個(gè)元素地址,4/8

字符數(shù)組

char a[] = {'a','b','c','d','e','f'};
printf("%d\n",sizeof(a));
printf("%d\n",sizeof(a+0));
printf("%d\n",sizeof(*a));
printf("%d\n",sizeof(a[1]));
printf("%d\n",sizeof(&a));
printf("%d\n",sizeof(&a+1));
printf("%d\n",sizeof(&a[0]+1));

和上面同理,再來看看編譯器怎么解答的:

在這里插入圖片描述


1.a 是數(shù)組名,首元素地址計(jì)算整個(gè)數(shù)組大小為 6

2.a + 0,首元素地址 + 0 還是首元素地址,4/8

3.*a,首元素大小 ,1

4.1

5.&數(shù)組名為整個(gè)數(shù)組地址,4/8

6.跳過一個(gè)數(shù)組,下一個(gè)數(shù)組地址,4/8

7.第二個(gè)元素地址,4/8

這么簡單?nonono,這才剛剛開始

char a[] = {'a','b','c','d','e','f'};
printf("%d\n",strlen(a));
printf("%d\n",strlen(a+0));
printf("%d\n",strlen(*a));
printf("%d\n",strlen(a[1]));
printf("%d\n",strlen(&a));
printf("%d\n",strlen(&a+1));
printf("%d\n",strlen(&a[0]+1));

我還是先把運(yùn)行結(jié)果啪出來吧:

在這里插入圖片描述

誒?怪誒,打印7下出來2個(gè)?nnd給我玩陰的是吧。這里首先強(qiáng)調(diào)一下,sizeof 是操作符,海納百川來啥算啥,‘ \0 ’也會(huì)照收,而 strlen 是傲嬌的庫函數(shù),傲嬌在于strlen 針對(duì)的是 \0 之前的字符串長度(個(gè)數(shù)),而且不包含 ‘ \0 ’。

1.a 數(shù)組名,沒有在 sizeof 內(nèi)部,為首元素地址,我們知道 strlen 在遇到 \0 之前是不會(huì)停下來的,字符數(shù)組我們沒有給到 \0就是沒有,因此什么時(shí)候遇到他我們不知道,起碼會(huì)比當(dāng)前數(shù)組大,不知道嘛時(shí)候停就是個(gè)隨機(jī)值

在這里插入圖片描述

2.同理,隨機(jī)值

3.首元素地址解引用為首元素 ‘a’,strlen 需要的是一個(gè)地址,此時(shí)會(huì)從把‘a’ 默認(rèn)為一個(gè)地址,a的ASCII碼值為 97,就會(huì)從內(nèi)存中地址為 97 的地方開始往后數(shù)字符個(gè)數(shù),但是注意 97 不屬于我原本分配的內(nèi)容,屬于非法訪問內(nèi)存,直接報(bào)錯(cuò)崩潰垮掉

4.同理,報(bào)錯(cuò)

5.數(shù)組的地址,雖然和 strlen 參數(shù)類型有所差異,但還是從第一個(gè)位置向后數(shù),那就是隨機(jī)值啦

6.跳過一個(gè)數(shù)組的地址,依然是隨機(jī)值

7.第二個(gè)元素地址,依然依然是隨機(jī)值

那么就又雙可以聯(lián)想到字符串了,引入指針變量進(jìn)行討論:

char* p = "abcdef";
printf("%d\n",sizeof(p));
printf("%d\n",sizeof(p+1));
printf("%d\n",sizeof(*p));
printf("%d\n",sizeof(p[0]));
printf("%d\n",sizeof(&p));
printf("%d\n",sizeof(&p+1));
printf("%d\n",sizeof(&p[0]+1));

printf("%d\n",strlen(p));
printf("%d\n",strlen(p+1));
printf("%d\n",strlen(*p));
printf("%d\n",strlen(p[0]));
printf("%d\n",strlen(&p));
printf("%d\n",strlen(&p+1));
printf("%d\n",strlen(&p[0]+1));

直接看結(jié)果吧,這下就感覺出有點(diǎn)意義不明了,結(jié)果對(duì)應(yīng)哪個(gè)數(shù)據(jù)都不知道了,所以這時(shí)候自主分析的價(jià)值就出來了

在這里插入圖片描述

  • p是一個(gè)指針,sizeof 算指針的大小,4/8字節(jié)
  • p+1,就是 p 的值加1,字符指針p是一個(gè)地址,數(shù)值上+1是 b 的地址,所以大小 4/8字節(jié)
  • p 為char* 的指針,解引用訪問首元素,大小為 1
  • 小問號(hào)你是否有很多朋友,指針為啥還可以 [0] ?其實(shí) p[0] 等價(jià)于 *(p+0),p是首元素地址,p+0亦是,解引用出來就是首元素,1
  • p是地址,&p是對(duì)地址取地址,也就是二級(jí)指針,是地址那就是 4/8
  • 跳過一個(gè)char*的地址即跳過了一個(gè)p的地址,本質(zhì)上還是地址,4/8
  • p[0]為首元素,取地址+1 為第二個(gè)元素的地址,4/8

1.在 “abcdef”中是隱含了一個(gè)‘ \0 ’的,所以傳入p算出大小為 6

2.同理,從第二個(gè)元素開始,5

3.解引用為a,97,報(bào)錯(cuò)

4,等價(jià)于*p,就是首元素,報(bào)錯(cuò)

5,取數(shù)組地址的地址往后數(shù)字符串,為隨機(jī)值

6.+1跳過一個(gè)地址的地址往后數(shù),依然是隨機(jī)值

7.第二個(gè)元素的地址往后數(shù),隨機(jī)值,等價(jià)于 p+1

二維數(shù)組

int a[3][4] = {0};
printf("%d\n",sizeof(a));
printf("%d\n",sizeof(a[0][0]));
printf("%d\n",sizeof(a[0]));
printf("%d\n",sizeof(a[0]+1));
printf("%d\n",sizeof(*a[0]+1));
printf("%d\n",sizeof(a+1));
printf("%d\n",sizeof(*(a+1)));
printf("%d\n",sizeof(&a[0]+1));
printf("%d\n",sizeof(*(&a[0]+1)));
printf("%d\n",sizeof(*a));
printf("%d\n",sizeof(a[3]));

看一下運(yùn)行結(jié)果:

在這里插入圖片描述

1.a數(shù)組名,為整個(gè)數(shù)組,124 = 48

2.數(shù)組首元素,14 = 4

3.數(shù)組第一行元素,44 = 16

4.a[0]此時(shí)為首元素地址,即a[0]|0] 地址,+1為 a[0]|1] 地址,4/8

5.等價(jià)于a[0] [1],,14 = 4

6.數(shù)組名不是單獨(dú)存放為第一行地址,+1表示第二行地址,4/8

7.解引用為第二行元素,44 = 16

8.a[0]為第一行地址,&a[0]+1為第二行地址,4/8

9.解引用為第二行元素,44 = 16

10.解引用首元素地址為第一行,44 = 16

11.淦!好怪!數(shù)組只有3行卻搞出個(gè) a[3],這不越界了嗎?其實(shí)編譯器會(huì)很聰明的自行推算,按照已給數(shù)組排列就是 44 = 16

整點(diǎn)硬菜

熱身完了,來整點(diǎn)題目,讓你混亂的大腦脈動(dòng)回來(雪上加霜

1.

int main()
{
int a[6] = {1,2,3,4,5,6};
int *ptr = (*int)(&a+1);
printf("%d %d",*(a + 1),*(ptr - 1));
return 0;
}

ptr 是int類型指針,&a是數(shù)組地址,+1跳過一個(gè)數(shù)組,指向數(shù)組末位的地址,強(qiáng)轉(zhuǎn)為 int* 類型,*(a+1)首元素地址+1再解引用得到第二個(gè)元素 ,ptr - 1指向 5 的地址,所以答案為 2,5。

2.

//假設(shè)stu 大小為 20 字節(jié)
struct stu
{
char* name;
int age;
float score;
} *p;
int main()
{
(struct  stu*)p =0x100000;
printf("%p\n",p + 0x1);
printf("%p\n",(unsigned long)p + 0x1);
printf("%p\n",(unsigned int*)p + 0x1);
return 0;
}

p是一個(gè)指針類型指向結(jié)構(gòu)體,代表結(jié)構(gòu)體的地址, p + 0x1 就是地址數(shù)值上進(jìn)行 + 0x1 操作,p = 0x100000 ,我們知道 int* +1 跳過4個(gè)字節(jié),char* + 1跳過1 個(gè)字節(jié),我們這里是結(jié)構(gòu)體類型,就跳過 20 個(gè)字節(jié),20 化成16進(jìn)制相加就是 0x100014

p 強(qiáng)轉(zhuǎn)為 unsigned long 其實(shí)就是整型,p 就是一個(gè)純純的數(shù)字了,那0x100000 既然已經(jīng)是“數(shù)字”了,那就有了可以直接加減的屬性,就是 0x100001

p強(qiáng)轉(zhuǎn)成無符號(hào)整型指針類型, 一個(gè)指針類型是 4 個(gè)字節(jié),結(jié)果就是 0x100004

到這里是不是有內(nèi)味兒了,那咱繼續(xù)

3.

int main()
{
int a[4] = {1,2,3,4};
int* ptr = (int*)(&a+1);
int* ptr2 = (int*)((int)a+1);
printf("%x %x",ptr[-1],*ptr2);
return 0;
}

此題請(qǐng)仔細(xì)思考,大坑警告!

ptr 為整型指針,&a為整個(gè)數(shù)組地址,+1跳過整個(gè)數(shù)組來到末位的地址,再強(qiáng)轉(zhuǎn)成 int * 類型(這里大可不必,因?yàn)樗緛砭褪且粋€(gè) int * 指針)ptr[-1] 等價(jià)于 * (ptr - 1),再代入 ptr 就代表最末地址 -1 來到 4 的地址,ptr[-1 ]就是 4。

ptr2中 a為首元地址,這里注意優(yōu)先級(jí)問題,先強(qiáng)轉(zhuǎn)成 int 就是個(gè)純純的數(shù)字可以直接進(jìn)行 +1 操作,即地址進(jìn)行了數(shù)值+1,格局高不高就要看下一步,接下來需要考慮 大小端問題,因?yàn)槲覀兪切《舜鎯?chǔ),按照低位字節(jié)在低地址處,所以 1,2,3,4 在內(nèi)存中是這樣的:

…… | 01 | 00 | 00 | 00 | 02 | 00 | 00 | 00 | 03 | 00 | ……

假設(shè) 01 地址是 0x01,int 強(qiáng)轉(zhuǎn)后 a +1 偏移一個(gè)字節(jié),指向的就是 01 后面一個(gè) 00 的位置,所以 ptr2 就指向這個(gè)位置,我們解引用拿到他的值就是整型大小的值就是 00 00 00 02,再以小端的形式拿出來就是 20 00 00 00。

4.

int main()
{
int a[3][2] = {(0,1),(2,3),(4,5)};
int* p;
p = a[0];
printf("%d",p[0]);
return 0;
}

p[0] 等價(jià)于*(p+0),p = a[0], 就是*a[0] ,a[0] 是首元素地址,那么問題來了:是 0 的地址嗎?

請(qǐng)仔細(xì)看看我們二維數(shù)組的逗號(hào)表達(dá)式,其實(shí)整個(gè)數(shù)組就只有 3 個(gè)元素:1,3 5;他們?cè)跀?shù)組中排列出來是:

1 | 3
5 | 0
0 | 0

所以解引用出來就是 1。

今天就到這兒吧,摸了家人們

以上就是賭你會(huì)懵的C語言指針進(jìn)階的詳細(xì)內(nèi)容,更多關(guān)于C語言指針進(jìn)階的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Qt中CQGUI框架之陰影圓角窗口實(shí)現(xiàn)

    Qt中CQGUI框架之陰影圓角窗口實(shí)現(xiàn)

    這篇文章主要介紹了Qt中CQGUI框架之陰影圓角窗口實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • C++ Boost PointerContainer智能指針詳解

    C++ Boost PointerContainer智能指針詳解

    智能指針是一種像指針的C++對(duì)象,但它能夠在對(duì)象不使用的時(shí)候自己銷毀掉。雖然STL提供了auto_ptr,但是由于不能同容器一起使用(不支持拷貝和賦值操作),因此很少有人使用。它是Boost各組件中,應(yīng)用最為廣泛的一個(gè)
    2022-11-11
  • C語言數(shù)組元素循環(huán)右移問題及解決方法

    C語言數(shù)組元素循環(huán)右移問題及解決方法

    這篇文章主要介紹了C語言數(shù)組元素循環(huán)右移問題,本文通過多種方法給大家分享解決方案,通過實(shí)例代碼講解,對(duì)大家的工作或?qū)W習(xí)具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-03-03
  • C++標(biāo)準(zhǔn)模版庫(STL)之vector容器詳解

    C++標(biāo)準(zhǔn)模版庫(STL)之vector容器詳解

    vector的功能和水桶一樣,就是用來裝東西的,并且vector還提供了迭代器來很方便的訪問這些數(shù)據(jù),下面就讓我們一起看下如何使用C++的vector吧
    2023-03-03
  • 基于malloc與free函數(shù)的實(shí)現(xiàn)代碼及分析

    基于malloc與free函數(shù)的實(shí)現(xiàn)代碼及分析

    本篇文章介紹了malloc與free函數(shù)的實(shí)現(xiàn)代碼及分析。需要的朋友參考下
    2013-05-05
  • C語言實(shí)現(xiàn)帶頭結(jié)點(diǎn)的鏈表的創(chuàng)建、查找、插入、刪除操作

    C語言實(shí)現(xiàn)帶頭結(jié)點(diǎn)的鏈表的創(chuàng)建、查找、插入、刪除操作

    這篇文章主要介紹了C語言實(shí)現(xiàn)帶頭結(jié)點(diǎn)的鏈表的創(chuàng)建、查找、插入、刪除操作方法,對(duì)于了解數(shù)據(jù)結(jié)構(gòu)中鏈表的各項(xiàng)操作有很好的借鑒價(jià)值,需要的朋友可以參考下
    2014-09-09
  • C++類成員函數(shù)后面加const問題

    C++類成員函數(shù)后面加const問題

    這篇文章主要介紹了C++類成員函數(shù)后面加const問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • C++實(shí)現(xiàn)教職工管理系統(tǒng)課程設(shè)計(jì)

    C++實(shí)現(xiàn)教職工管理系統(tǒng)課程設(shè)計(jì)

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)教職工管理系統(tǒng)課程設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 詳解Matlab如何繪制圓角半透明圖例

    詳解Matlab如何繪制圓角半透明圖例

    目前MATLAB的legend圖例是不支持圓角和半透明的,所以本文將自制實(shí)現(xiàn)圓角半透明圖例。文中的示例代碼講解詳細(xì),需要的可以參考一下
    2022-05-05
  • c語言簡單實(shí)現(xiàn)文件 r/w 操作方法

    c語言簡單實(shí)現(xiàn)文件 r/w 操作方法

    由于在 C 語言中 '\' 一般是轉(zhuǎn)義字符的起始標(biāo)志,故在路徑中需要用兩個(gè) '\' 表示路徑中目錄層次的間隔,也可以使用 '/' 作為路徑中的分隔符,本文重點(diǎn)給大家介紹用c語言簡單實(shí)現(xiàn)文件 r/w 操作方法,感興趣的朋友一起學(xué)習(xí)吧
    2021-05-05

最新評(píng)論

海兴县| 隆德县| 克拉玛依市| 海林市| 彩票| 铁岭市| 凯里市| 南城县| 云南省| 星子县| 平安县| 忻州市| 石台县| 瓮安县| 土默特右旗| 建瓯市| 合江县| 湟中县| 天水市| 乌审旗| 陈巴尔虎旗| 四川省| 惠东县| 吉安县| 民县| 姜堰市| 乌拉特后旗| 富裕县| 阳城县| 札达县| 若羌县| 会宁县| 东阳市| 通道| 肇州县| 密云县| 呈贡县| 珲春市| 阳山县| 旅游| 兴仁县|