在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

數(shù)組和指針有什么區(qū)別

Q4MP_gh_c472c21 ? 來(lái)源:老吳嵌入式 ? 作者:吳偉東Jack ? 2021-11-22 09:56 ? 次閱讀

一、能力錯(cuò)覺(jué)

當(dāng)書(shū)本(或谷歌)擺在眼前時(shí),大腦會(huì)產(chǎn)生錯(cuò)覺(jué),以為學(xué)習(xí)材料也同樣存入了大腦,閱讀畢竟比回想簡(jiǎn)單多了。

以為反復(fù)的閱讀資料就是自己已經(jīng)掌握知識(shí),這就是能力錯(cuò)覺(jué)

解決能力錯(cuò)覺(jué)的方法

  • 積極回想——讓大腦提取關(guān)鍵概念,而非通過(guò)重復(fù)閱讀被動(dòng)地獲取知識(shí),這樣才能高效地學(xué)習(xí)。

現(xiàn)在網(wǎng)絡(luò)上盛行各種it類(lèi)的視頻教程,我不否認(rèn)不少視頻教程是高質(zhì)量的,但是所有視頻類(lèi)資料都有一個(gè)問(wèn)題:

  • 可以讓人不用閱讀書(shū)籍,減少思考,只要被動(dòng)地聽(tīng)老師們講課就能舒舒服服地獲取到知識(shí),這很容易會(huì)讓某些初級(jí)的軟件開(kāi)發(fā)人員形成能力錯(cuò)覺(jué),仿佛視頻里寫(xiě)過(guò)的代碼,解決過(guò)的 bug 都是自己已經(jīng)學(xué)到的知識(shí)似的。

有效的解決辦法是

  • 公開(kāi)學(xué)習(xí)筆記和練習(xí)代碼。公開(kāi)學(xué)習(xí)筆記的目的是借助外部壓力,高效回想,進(jìn)而提高自己的學(xué)習(xí)標(biāo)準(zhǔn)。

  • 另外,公開(kāi)寫(xiě)作則會(huì)給你的寫(xiě)作增加很多維度的外部壓力,你會(huì)想如何讓別人更好地理解我要表達(dá)的意思;如何傳遞更多價(jià)值,讓別人讀完有所收獲;如何讓更多人看到;如何讓別人讀得下去;如何排版讓大家看得更舒服;


二、數(shù)組和指針有什么區(qū)別?

正文目錄:

1.用于聲明時(shí)兩者有重大區(qū)別
2. 你真的理解聲明和定義嗎?
3. 數(shù)組和指針的底層是如何訪問(wèn)數(shù)據(jù)的?
4. 哪些場(chǎng)景可以用指針代替數(shù)組?
5. 為什么C語(yǔ)言要把數(shù)組形參退化為指針?
6. 如何使用指針訪問(wèn)多維數(shù)組?
7.相關(guān)面試題

寫(xiě)作目的:

  • 正確看待數(shù)組和指針。

測(cè)試環(huán)境:

  • Ubuntu 16.04
  • Gcc 5.4.0

1、用于聲明時(shí)兩者有重大區(qū)別

1) 誤導(dǎo)新手的說(shuō)法:

由于數(shù)組和指針的所謂等價(jià)性非常接近,不少程序員有時(shí)忽視了二者之間的其他重要區(qū)別 ,最誤導(dǎo)新手的說(shuō)法之一就是 “數(shù)組和指針是相同的",這是一種非常危險(xiǎn)的說(shuō)法。

看下面這個(gè)例子:

externint*x;
externintx[];
  • 第一條語(yǔ)句聲明 x 是個(gè) int 型的指針;

  • 第二條語(yǔ)句聲明 x 是個(gè) int 型數(shù)組,長(zhǎng)度尚未確定,即存儲(chǔ)長(zhǎng)度在別處定義。

2) 為什么有些人會(huì)誤以為指針和數(shù)組總是可以互換?

最主要原因是
對(duì)數(shù)組的引用 ( x[i] ) 總是可以寫(xiě)成對(duì)指針的引用 ( *(x+i) )

  • 即確實(shí)存在一種指針和數(shù)組的定義完全相同的上下文環(huán)境。不幸的是,這只是數(shù)組的一種極為普通的用法,并非所有情況下都是如此。

2、你真的理解聲明和定義嗎?

想要要真正理解為什么 extern int *x 不等于 extern int x[],我們首先需要搞清楚什么是聲明,什么是定義。

1) 鏈接器的視角:

  • C 語(yǔ)言中的對(duì)象必須有且只有一個(gè)定義,但它可以有多個(gè) extern 聲明。這里所說(shuō)的對(duì)象跟 C++ 中的對(duì)象并無(wú)關(guān)系,這里說(shuō)的對(duì)象是 從鏈接器的視角來(lái)看的,鏈接器將各個(gè)函數(shù)、變量都視為對(duì)象

2) 定義和聲明的聯(lián)系與區(qū)別:

  • 定義是一種特殊的聲明,它創(chuàng)建了一個(gè)對(duì)象;聲明簡(jiǎn)單地說(shuō)明了在其他地方創(chuàng)建的對(duì)象的名字。

  • 定義只能出現(xiàn)在一個(gè)地方,它指定了對(duì)象的類(lèi)型并分配內(nèi)存以創(chuàng)建新的對(duì)象。聲明可以多次出現(xiàn) 以描述對(duì)象的類(lèi)型,用于指代其他地方定義的對(duì)象,它不為對(duì)象分配內(nèi)存。

  • extern 對(duì)象聲明告訴編譯器對(duì)象的類(lèi)型和名字,對(duì)象的內(nèi)存分配則在別處進(jìn)行。由于并未在聲明中為數(shù)組分配內(nèi)存,所以并不需要提供關(guān)于數(shù)組長(zhǎng)度的信息 (多維數(shù)組例外)。

3) 總結(jié)成一句話:

  • 定義 = 聲明 + 分配內(nèi)存 (創(chuàng)建對(duì)象)

4) 回過(guò)頭來(lái)看這個(gè)例子:

externint*x;
externintx[];

前者聲明了一個(gè)指針,后者聲明了一個(gè)數(shù)組,那么它們對(duì)應(yīng)的指針和數(shù)組的定義(最重要的是內(nèi)存分配) 能相等嗎?


3、數(shù)組和指針的底層是如何訪問(wèn)數(shù)據(jù)的?

現(xiàn)在我們來(lái)看看指針和數(shù)組的定義與使用。

1) "地址 X (Address)" 和 "地址 X 的內(nèi)容(Contents of Address)" 之間的區(qū)別:

對(duì)于"地址 X" 和 "地址 X 的內(nèi)容",在 C 語(yǔ)言中是用同一個(gè)符號(hào)來(lái)表示這兩樣?xùn)|西,由編譯器根據(jù)上下文環(huán)境判斷它的具體含義。

2) 看下面這個(gè)例子:

X=Y
  • 符號(hào) X 的含義是 X 所代表的地址,它是左值,編譯時(shí)可知;

  • 符號(hào) Y 的含義是 Y 所代表的地址上的內(nèi)容,它是右值,運(yùn)行時(shí)才知;

  • 左值包括可修改的左值和不可修改的左值,C 語(yǔ)言中,一般的數(shù)據(jù)類(lèi)型都是都可作為可修改的左值,只有數(shù)組是不可修改的左值;

  • 數(shù)組的地址在編譯時(shí)可知,編譯器有了這個(gè)地址 (即數(shù)組首地址),就可以直接進(jìn)行讀寫(xiě)操作。而指針必須在運(yùn)行時(shí)取得它的當(dāng)前值,然后才能對(duì)它進(jìn)行解除引用操作,才能進(jìn)行讀寫(xiě)操作。

3) 數(shù)組和指針的訪問(wèn)方式是不同的:

chara[9]="abcedefgh";

  • 上面這個(gè)例子中,a 是一個(gè)數(shù)組。

  • 在編譯器符號(hào)表里有一個(gè)符號(hào) a ,它的地址為9980;

  • 數(shù)組內(nèi)的字符都可以從這個(gè)地址 + 偏移量找到,編譯器甚至并不需要知道數(shù)組的總長(zhǎng)度;

charc='F';
char*p=&c;

  • 上面這個(gè)例子中,p 是一個(gè)指針。

  • 在編譯器符號(hào)表中有一個(gè)符號(hào) p, 它的地址為 4624;

  • p 指向的對(duì)象是一個(gè)字符。為了取得這個(gè)字符,必須得到地址 p 的內(nèi)容 (5081),把它作為字符的地址并從這個(gè)地址中取得這個(gè)字符 ('F')。

4) 當(dāng)定義為指針 (char *p),并以數(shù)組方式 (p[i]) 引用時(shí)會(huì)發(fā)生什么?

char*p=”abcdefgh”
printf("%c
",p[3]);

char*a=”abcdefgh”
printf("%c
",a[3]);
  • p[3] 和 a[3] 都能成功訪問(wèn)到字符 'd';

  • a[i] 表示 "從 a 的地址開(kāi)始,前進(jìn) i 步,每步都是一個(gè)字符(數(shù)組類(lèi)型的長(zhǎng)度)”;

  • p[i] 表示 "從 p 所指的地址開(kāi)始,前進(jìn) i 步,每步都是一個(gè)字符(即指針?biāo)割?lèi)型的長(zhǎng)度)”;

  • 所以,當(dāng)你用 extern char *p 來(lái)聲明 char p[10]時(shí),編譯器會(huì)把 p[i] 當(dāng)成一個(gè)指針(Address),然后去獲取 *(p[i]) (即 Content of Addrss),這時(shí)最好的結(jié)果是程序立馬崩潰,你能快點(diǎn)發(fā)現(xiàn)問(wèn)題。最糟糕的情況是,程序崩潰在將來(lái)的某個(gè)時(shí)刻,你則 debug 到懷疑人生


4、哪些場(chǎng)景可以用指針代替數(shù)組?

數(shù)組和指針容易混淆使用的 2 大類(lèi)場(chǎng)景:

  • 聲明

  • 在表達(dá)式中使用;

1) 聲明:
聲明的場(chǎng)景包括 3 種:

  • 1> 不可以的場(chǎng)景:定義也是一種聲明,定義數(shù)組時(shí)不能用指針的形式;

  • 2> 不可以的場(chǎng)景:extern 數(shù)組時(shí)不能改寫(xiě)成指針的形式, 例如:

intchar[10];//define
externchara[];//ok
externchar*a;//error
  • 3> 可以的場(chǎng)景:函數(shù)的形參,用數(shù)組形式還是指針形式,隨你自己的喜好。

2) 在表達(dá)式中使用:

  • 在表達(dá)式中,指針形式和數(shù)組形式等效。

3) 幾條重要的規(guī)則:

  • 規(guī)則1:"表達(dá)式中的數(shù)組名" 就是指針;

  • 規(guī)則2:把數(shù)組下標(biāo)可當(dāng)作指針的偏移量;

  • 規(guī)則3: "作為函數(shù)參數(shù)的數(shù)組名" 等同于指針;


5、為什么C語(yǔ)言要把數(shù)組形參退化為指針?

1) 出于效率的考慮:
  • 在 C 語(yǔ)言中,所有非數(shù)組形式的數(shù)據(jù)實(shí)參均以傳值形式(對(duì)實(shí)參作一份拷貝并傳遞給調(diào)用的函數(shù),函數(shù)不能修改作為實(shí)參的實(shí)際變量的值)。

  • 如果要拷貝整個(gè)數(shù)組,無(wú)論在時(shí)間上還是在內(nèi)存空間上的開(kāi)銷(xiāo)都可能是非常大的

2) 出于簡(jiǎn)化編譯器的考慮:

  • 在 C 語(yǔ)言中,所有的數(shù)組在作為參數(shù)傳遞時(shí)都轉(zhuǎn)換為指向數(shù)組起始地址的指針,而其他的參數(shù)均采用傳值調(diào)用。

  • 允許程序員把形參聲明為數(shù)組 (程序員打算傳遞給函數(shù)的東西) 或者指針 (函數(shù)實(shí)際所接收到的東西)。在函數(shù)內(nèi)部,編譯器始終把它當(dāng)作一個(gè)指向數(shù)組第一個(gè)元素的指針

3) 看下面這個(gè)例子:

staticintarray[10],array2[10];

staticvoidfunc1(int*ptr)
{
ptr[1]=3;
*ptr=3;
ptr=array2;
}

staticvoidfunc2(intarray[])
{
array[1]=3;
*array=3;
array=array2;//OK,becausearrayisapointer
printf("*array=%d
",*array);
}

intmain(void)
{
func1(array);
func2(array);

array[1]=3;
*array=3;
array=array2;//ERROR
return0;
}

編譯運(yùn)行:

// main 中調(diào)用 array = array2時(shí):
11:error:assignmenttoexpressionwitharraytype

//去掉 main / array = array2時(shí):
$./point_array_arg
*array=0

6、如何使用指針訪問(wèn)多維數(shù)組?

1) C 語(yǔ)言的多維數(shù)組:

  • 采用最右的下標(biāo)先變化原則,其最大的用途是存儲(chǔ)多個(gè)字符串;

  • 單個(gè)元素的存儲(chǔ)和引用實(shí)際上是以線性形式排列在內(nèi)存中;

  • 不能把一個(gè)數(shù)組賦值給另一個(gè)數(shù)組,因?yàn)閿?shù)組作為一個(gè)整體不能成為賦值的對(duì)象;

  • 可以把數(shù)組名賦值給一個(gè)指針,是因?yàn)?strong>在表達(dá)式中的數(shù)組名被編譯器當(dāng)作一個(gè)指針;

  • 指針下標(biāo)引用的規(guī)則告訴我們 pea[i][j] 被編譯器解釋為 ((pea + i) + j);

  • 可以通過(guò)聲明一個(gè)一維指針數(shù)組 ( (char *)pea[4],下標(biāo)方括號(hào)的優(yōu)先級(jí)比指針的星號(hào)高),其中每個(gè)指針指向一個(gè)字符串,來(lái)取得類(lèi)似二維字符數(shù)組的效果;

7、相關(guān)面試題

1) 找錯(cuò):計(jì)算字符串長(zhǎng)度

下面這段程序是為了把字符串轉(zhuǎn)換為大寫(xiě):

#include

voidUpperCase(charstr[])
{
inttest=sizeof(str);
inttest2=sizeof(str[0]);

for(size_ti=0;i<sizeof(str)/sizeof(str[0]);++i){
if('a'<=str[i]?&&?str[i]<='z')
str[i]-=('a'-'A');
}
}



intmain(void)
{

charstr[]="aBcDeefGHijKL";
printf("Thelengthofstris%d
",sizeof(str)/sizeof(str[0]));

UpperCase(str);
printf("result:%s
",str);
return0;
}

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

$./sizeof_array
Thelengthofstris14
result:ABCDEEFGHijKL

問(wèn)題出在 UpperCase() 里的 sizeof(str),這里的 str 是一個(gè)指針而不是數(shù)組

正確的寫(xiě)法有2種

  • 給UpperCase傳遞長(zhǎng)度參數(shù),這是最穩(wěn)妥的方式。
  • 在UpperCase 內(nèi)使用strlen 獲取字符串長(zhǎng)度,這種方法僅適用于以 ‘’ 結(jié)尾的字符數(shù)組;
責(zé)任編輯:haq
聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 指針
    +關(guān)注

    關(guān)注

    1

    文章

    482

    瀏覽量

    70616
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4841

    瀏覽量

    69176
  • 數(shù)組
    +關(guān)注

    關(guān)注

    1

    文章

    417

    瀏覽量

    26037

原文標(biāo)題:你知道數(shù)組和指針有什么區(qū)別嗎?

文章出處:【微信號(hào):gh_c472c2199c88,微信公眾號(hào):嵌入式微處理器】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    指針數(shù)組和二維數(shù)組有沒(méi)有區(qū)別

    指針數(shù)組和二維數(shù)組有沒(méi)有區(qū)別?比如這樣的兩個(gè)代碼。 int main(){ char *s1[] = { "hello", "world", "total" }; char s2[][
    的頭像 發(fā)表于 11-24 11:12 ?230次閱讀

    FCCSP與FCBGA都是倒裝有什么區(qū)別

    本文簡(jiǎn)單介紹了倒裝芯片球柵陣列封裝與倒裝芯片級(jí)封裝的概念與區(qū)別。 FCCSP與FCBGA都是倒裝,怎么區(qū)分?什么區(qū)別
    的頭像 發(fā)表于 11-16 11:48 ?2444次閱讀
    FCCSP與FCBGA都是倒裝有<b class='flag-5'>什么區(qū)別</b>

    美國(guó)多IP服務(wù)器和美國(guó)多服務(wù)器什么區(qū)別

    美國(guó)多IP服務(wù)器和美國(guó)多服務(wù)器什么區(qū)別 美國(guó)多IP服務(wù)器和美國(guó)多服務(wù)器在概念、功能以及應(yīng)用場(chǎng)景上存在明顯的區(qū)別。主機(jī)推薦小編為您整理發(fā)布美國(guó)多IP服務(wù)器和美國(guó)多服務(wù)器
    的頭像 發(fā)表于 11-11 10:22 ?281次閱讀

    C語(yǔ)言指針運(yùn)算符詳解

    在C語(yǔ)言中,當(dāng)你一個(gè)指向數(shù)組中某個(gè)元素的指針時(shí),你可以對(duì)該指針執(zhí)行某些算術(shù)運(yùn)算,例如加法或減法。這些運(yùn)算可以用來(lái)遍歷數(shù)組中的元素,如ptr
    的頭像 發(fā)表于 10-30 11:16 ?325次閱讀

    RTOS與Linux到底什么區(qū)別

    很多做嵌入式開(kāi)發(fā)的小伙伴都存在這樣的疑惑:RTOS與Linux到底什么區(qū)別
    的頭像 發(fā)表于 10-29 09:53 ?617次閱讀

    請(qǐng)問(wèn)VCA821和VCA824什么區(qū)別

    請(qǐng)問(wèn)VCA821和VCA824什么區(qū)別??jī)蓚€(gè)芯片的概述基本都一樣,但是細(xì)看里面的資料會(huì)發(fā)現(xiàn)一些參數(shù)圖表好像是不一樣的。那到底怎么看,什么區(qū)別
    發(fā)表于 09-05 07:59

    面試常考+1:函數(shù)指針指針函數(shù)、數(shù)組指針指針數(shù)組

    在嵌入式開(kāi)發(fā)領(lǐng)域,函數(shù)指針指針函數(shù)、數(shù)組指針指針數(shù)組是一些非常重要但又容易混淆的概念。理解它
    的頭像 發(fā)表于 08-10 08:11 ?1005次閱讀
    面試常考+1:函數(shù)<b class='flag-5'>指針</b>與<b class='flag-5'>指針</b>函數(shù)、<b class='flag-5'>數(shù)組</b><b class='flag-5'>指針</b>與<b class='flag-5'>指針</b><b class='flag-5'>數(shù)組</b>

    請(qǐng)問(wèn)ESPTOUCH和AIRKISS什么區(qū)別

    請(qǐng)問(wèn)ESPTOUCH和AIRKISS什么區(qū)別?謝謝!
    發(fā)表于 07-12 12:44

    RV 和ARM什么區(qū)別

    district RV 和ARM什么區(qū)別
    發(fā)表于 06-26 12:41

    STM32Cube庫(kù)和standard peripheral library什么區(qū)別

    STM32Cube庫(kù)和standard peripheral library什么區(qū)別
    發(fā)表于 05-16 06:52

    指針式萬(wàn)用表和數(shù)字萬(wàn)用表什么區(qū)別

    指針式萬(wàn)用表和數(shù)字萬(wàn)用表在多個(gè)方面存在顯著的區(qū)別,這些區(qū)別主要體現(xiàn)在以下幾個(gè)方面。
    的頭像 發(fā)表于 05-09 17:22 ?1974次閱讀

    Ethernet和EtherCAT兩者什么區(qū)別和聯(lián)系?

    Ethernet和EtherCAT兩者什么區(qū)別和聯(lián)系?
    發(fā)表于 04-12 07:13

    線路板的層和階什么區(qū)別

    線路板的層和階什么區(qū)別
    的頭像 發(fā)表于 02-23 17:27 ?889次閱讀

    數(shù)組和鏈表在內(nèi)存中的區(qū)別 數(shù)組和鏈表的優(yōu)缺點(diǎn)

    數(shù)組和鏈表在內(nèi)存中的區(qū)別 數(shù)組和鏈表的優(yōu)缺點(diǎn)? 數(shù)組和鏈表是常見(jiàn)的數(shù)據(jù)結(jié)構(gòu),用于組織和存儲(chǔ)數(shù)據(jù)。它們?cè)趦?nèi)存中的存儲(chǔ)方式以及優(yōu)缺點(diǎn)方面存在一些顯著的差異。本文將詳細(xì)探討這些差異以及它們的
    的頭像 發(fā)表于 02-21 11:30 ?1166次閱讀

    數(shù)組和鏈表區(qū)別

    數(shù)組和鏈表的區(qū)別,這個(gè)問(wèn)題,不僅面試中經(jīng)常遇到,考研的同學(xué)也得掌握才行。
    的頭像 發(fā)表于 02-19 15:33 ?593次閱讀
    <b class='flag-5'>數(shù)組</b>和鏈表<b class='flag-5'>有</b>何<b class='flag-5'>區(qū)別</b>
    主站蜘蛛池模板: www.a级片| 噜噜爽| 欧美一级看片a免费观看 | 久久久99精品免费观看精品 | 欧美黄色录像视频 | 黄色日本视频 | 亚洲色播永久网址大全 | avtom影院永久转四虎入口 | 国产精品欧美一区二区三区不卡 | 大学生一级特黄的免费大片视频 | 国产精品福利一区 | 天天干夜夜躁 | 狠狠色狠狠色综合 | 最新激情网 | 色综合色综合 | 亚洲 欧美 日韩 在线 中文字幕 | 免费一级毛片在级播放 | 日本午夜片 | 美女扒开尿囗给男生桶爽 | 日本三级特黄 | www.a级片| 日本不卡1 | 日本黄色大片免费观看 | 天堂资源bt种子在线 | 天天摸日日碰天天看免费 | 日韩在线天堂免费观看 | 五月天婷婷丁香中文在线观看 | 色宅男看片午夜大片免费看 | 婷婷月| 天天爽天天狼久久久综合 | 欧美成人激情在线 | 黄黄视频在线观看 | 六月丁香婷婷激情 | 一级在线免费视频 | 四虎永久精品免费网址大全 | 国产精品国产三级在线高清观看 | 亚洲入口无毒网址你懂的 | 欧美黄业| 五月亭亭六月丁香 | 在线播放一区二区精品产 | 一级特色黄大片 |