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

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

數組和指針有什么區別

Q4MP_gh_c472c21 ? 來源:老吳嵌入式 ? 作者:吳偉東Jack ? 2021-11-22 09:56 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

一、能力錯覺

當書本(或谷歌)擺在眼前時,大腦會產生錯覺,以為學習材料也同樣存入了大腦,閱讀畢竟比回想簡單多了。

以為反復的閱讀資料就是自己已經掌握知識,這就是能力錯覺

解決能力錯覺的方法

  • 積極回想——讓大腦提取關鍵概念,而非通過重復閱讀被動地獲取知識,這樣才能高效地學習。

現在網絡上盛行各種it類的視頻教程,我不否認不少視頻教程是高質量的,但是所有視頻類資料都有一個問題:

  • 可以讓人不用閱讀書籍,減少思考,只要被動地聽老師們講課就能舒舒服服地獲取到知識,這很容易會讓某些初級的軟件開發人員形成能力錯覺,仿佛視頻里寫過的代碼,解決過的 bug 都是自己已經學到的知識似的。

有效的解決辦法是

  • 公開學習筆記和練習代碼。公開學習筆記的目的是借助外部壓力,高效回想,進而提高自己的學習標準。

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


二、數組和指針有什么區別?

正文目錄:

1.用于聲明時兩者有重大區別
2. 你真的理解聲明和定義嗎?
3. 數組和指針的底層是如何訪問數據的?
4. 哪些場景可以用指針代替數組?
5. 為什么C語言要把數組形參退化為指針?
6. 如何使用指針訪問多維數組?
7.相關面試題

寫作目的:

  • 正確看待數組和指針。

測試環境:

  • Ubuntu 16.04
  • Gcc 5.4.0

1、用于聲明時兩者有重大區別

1) 誤導新手的說法:

由于數組和指針的所謂等價性非常接近,不少程序員有時忽視了二者之間的其他重要區別 ,最誤導新手的說法之一就是 “數組和指針是相同的",這是一種非常危險的說法。

看下面這個例子:

externint*x;
externintx[];
  • 第一條語句聲明 x 是個 int 型的指針;

  • 第二條語句聲明 x 是個 int 型數組,長度尚未確定,即存儲長度在別處定義。

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

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

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

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

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

1) 鏈接器的視角:

  • C 語言中的對象必須有且只有一個定義,但它可以有多個 extern 聲明。這里所說的對象跟 C++ 中的對象并無關系,這里說的對象是 從鏈接器的視角來看的,鏈接器將各個函數、變量都視為對象

2) 定義和聲明的聯系與區別:

  • 定義是一種特殊的聲明,它創建了一個對象;聲明簡單地說明了在其他地方創建的對象的名字。

  • 定義只能出現在一個地方,它指定了對象的類型并分配內存以創建新的對象。聲明可以多次出現 以描述對象的類型,用于指代其他地方定義的對象,它不為對象分配內存。

  • extern 對象聲明告訴編譯器對象的類型和名字,對象的內存分配則在別處進行。由于并未在聲明中為數組分配內存,所以并不需要提供關于數組長度的信息 (多維數組例外)。

3) 總結成一句話:

  • 定義 = 聲明 + 分配內存 (創建對象)

4) 回過頭來看這個例子:

externint*x;
externintx[];

前者聲明了一個指針,后者聲明了一個數組,那么它們對應的指針和數組的定義(最重要的是內存分配) 能相等嗎?


3、數組和指針的底層是如何訪問數據的?

現在我們來看看指針和數組的定義與使用。

1) "地址 X (Address)" 和 "地址 X 的內容(Contents of Address)" 之間的區別:

對于"地址 X" 和 "地址 X 的內容",在 C 語言中是用同一個符號來表示這兩樣東西,由編譯器根據上下文環境判斷它的具體含義。

2) 看下面這個例子:

X=Y
  • 符號 X 的含義是 X 所代表的地址,它是左值,編譯時可知;

  • 符號 Y 的含義是 Y 所代表的地址上的內容,它是右值,運行時才知;

  • 左值包括可修改的左值和不可修改的左值,C 語言中,一般的數據類型都是都可作為可修改的左值,只有數組是不可修改的左值;

  • 數組的地址在編譯時可知,編譯器有了這個地址 (即數組首地址),就可以直接進行讀寫操作。而指針必須在運行時取得它的當前值,然后才能對它進行解除引用操作,才能進行讀寫操作。

3) 數組和指針的訪問方式是不同的:

chara[9]="abcedefgh";

  • 上面這個例子中,a 是一個數組。

  • 在編譯器符號表里有一個符號 a ,它的地址為9980;

  • 數組內的字符都可以從這個地址 + 偏移量找到,編譯器甚至并不需要知道數組的總長度;

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

  • 上面這個例子中,p 是一個指針。

  • 在編譯器符號表中有一個符號 p, 它的地址為 4624;

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

4) 當定義為指針 (char *p),并以數組方式 (p[i]) 引用時會發生什么?

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

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

  • a[i] 表示 "從 a 的地址開始,前進 i 步,每步都是一個字符(數組類型的長度)”;

  • p[i] 表示 "從 p 所指的地址開始,前進 i 步,每步都是一個字符(即指針所指類型的長度)”;

  • 所以,當你用 extern char *p 來聲明 char p[10]時,編譯器會把 p[i] 當成一個指針(Address),然后去獲取 *(p[i]) (即 Content of Addrss),這時最好的結果是程序立馬崩潰,你能快點發現問題。最糟糕的情況是,程序崩潰在將來的某個時刻,你則 debug 到懷疑人生


4、哪些場景可以用指針代替數組?

數組和指針容易混淆使用的 2 大類場景:

  • 聲明

  • 在表達式中使用;

1) 聲明:
聲明的場景包括 3 種:

  • 1> 不可以的場景:定義也是一種聲明,定義數組時不能用指針的形式;

  • 2> 不可以的場景:extern 數組時不能改寫成指針的形式, 例如:

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

2) 在表達式中使用:

  • 在表達式中,指針形式和數組形式等效。

3) 幾條重要的規則:

  • 規則1:"表達式中的數組名" 就是指針;

  • 規則2:把數組下標可當作指針的偏移量;

  • 規則3: "作為函數參數的數組名" 等同于指針;


5、為什么C語言要把數組形參退化為指針?

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

  • 如果要拷貝整個數組,無論在時間上還是在內存空間上的開銷都可能是非常大的

2) 出于簡化編譯器的考慮:

  • 在 C 語言中,所有的數組在作為參數傳遞時都轉換為指向數組起始地址的指針,而其他的參數均采用傳值調用。

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

3) 看下面這個例子:

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;
}

編譯運行:

// main 中調用 array = array2時:
11:error:assignmenttoexpressionwitharraytype

//去掉 main / array = array2時:
$./point_array_arg
*array=0

6、如何使用指針訪問多維數組?

1) C 語言的多維數組:

  • 采用最右的下標先變化原則,其最大的用途是存儲多個字符串;

  • 單個元素的存儲和引用實際上是以線性形式排列在內存中;

  • 不能把一個數組賦值給另一個數組,因為數組作為一個整體不能成為賦值的對象;

  • 可以把數組名賦值給一個指針,是因為在表達式中的數組名被編譯器當作一個指針;

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

  • 可以通過聲明一個一維指針數組 ( (char *)pea[4],下標方括號的優先級比指針的星號高),其中每個指針指向一個字符串,來取得類似二維字符數組的效果;

7、相關面試題

1) 找錯:計算字符串長度

下面這段程序是為了把字符串轉換為大寫:

#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;
}

運行結果:

$./sizeof_array
Thelengthofstris14
result:ABCDEEFGHijKL

問題出在 UpperCase() 里的 sizeof(str),這里的 str 是一個指針而不是數組

正確的寫法有2種

  • 給UpperCase傳遞長度參數,這是最穩妥的方式。
  • 在UpperCase 內使用strlen 獲取字符串長度,這種方法僅適用于以 ‘’ 結尾的字符數組;
責任編輯:haq
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 指針
    +關注

    關注

    1

    文章

    484

    瀏覽量

    71094
  • 代碼
    +關注

    關注

    30

    文章

    4892

    瀏覽量

    70422
  • 數組
    +關注

    關注

    1

    文章

    419

    瀏覽量

    26442

原文標題:你知道數組和指針有什么區別嗎?

文章出處:【微信號:gh_c472c2199c88,微信公眾號:嵌入式微處理器】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    GD32與STM32什么區別

    電子發燒友網站提供《GD32與STM32什么區別.docx》資料免費下載
    發表于 04-03 17:27 ?0次下載

    ATX主板和ITX主板什么區別

    在計算機硬件領域,主板是承載計算機核心組件的關鍵部件,其類型多樣,性能也各有千秋。那么ATX主板和ITX主板什么區別呢,下面來介紹一下:
    的頭像 發表于 03-03 08:47 ?621次閱讀

    私有云和公有云什么區別

    私有云和公有云在多個方面存在顯著的區別,以下是具體的比較,主機推薦小編為您整理發布私有云和公有云什么區別
    的頭像 發表于 02-20 10:38 ?651次閱讀

    AIGC和AI什么區別

    AIGC是AI在內容生成領域的一個特定應用方向,AI的技術發展為AIGC提供了基礎和支撐。那么,AIGC和AI什么區別呢?下面,AI部落小編帶您詳細了解。
    的頭像 發表于 02-20 10:33 ?752次閱讀

    請問ADS8343和ADS8341什么區別

    請問ADS8343和ADS8341什么區別
    發表于 01-08 06:30

    指針數組和二維數組有沒有區別

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

    DAC7742和DAC7741什么區別?

    DAC7742和DAC7741什么區別?
    發表于 11-22 08:31

    FCCSP與FCBGA都是倒裝有什么區別

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

    美國多IP服務器和美國多服務器什么區別

    美國多IP服務器和美國多服務器什么區別 美國多IP服務器和美國多服務器在概念、功能以及應用場景上存在明顯的區別。主機推薦小編為您整理發布美國多IP服務器和美國多服務器
    的頭像 發表于 11-11 10:22 ?633次閱讀

    C語言指針運算符詳解

    在C語言中,當你一個指向數組中某個元素的指針時,你可以對該指針執行某些算術運算,例如加法或減法。這些運算可以用來遍歷數組中的元素,如ptr
    的頭像 發表于 10-30 11:16 ?740次閱讀

    RTOS與Linux到底什么區別

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

    請問VCA821和VCA824什么區別

    請問VCA821和VCA824什么區別?兩個芯片的概述基本都一樣,但是細看里面的資料會發現一些參數圖表好像是不一樣的。那到底怎么看,什么區別
    發表于 09-05 07:59

    面試常考+1:函數指針指針函數、數組指針指針數組

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

    請問ESPTOUCH和AIRKISS什么區別

    請問ESPTOUCH和AIRKISS什么區別?謝謝!
    發表于 07-12 12:44

    RV 和ARM什么區別

    district RV 和ARM什么區別
    發表于 06-26 12:41
    主站蜘蛛池模板: 黄色视网站| 免费日本网站 | 99视频网站 | 国内久久久久高清影视 | 女张腿男人桶羞羞漫画 | 高清精品女厕在线观看 | 国产精品久久久久久一级毛片 | 色视频免费观看高清完整 | 天天操夜夜操美女 | 日韩黄色免费 | 国产精品久久久久网站 | 成人午夜大片免费7777 | 美女18毛片| 在线免费看高清视频大全 | 亚洲综合视频一区 | 狠狠干天天干 | 狠狠狠狠狠狠 | 欧美黄色大片免费 | 美女扒开尿口给男人爽的视频 | 欧美一区二区三区视频在线观看 | 深夜视频在线播放视频在线观看免费观看 | 一区二区三区四区国产精品 | 欧美一级黄色片在线观看 | 在线看片你懂得 | 伊人电影综合网 | 国产亚洲欧美一区二区 | aaaa在线观看 | 韩国三级理在线视频观看 | 中文字幕在线观看一区二区 | 精品久草 | 日本高清午夜色wwwσ | 最新亚洲情黄在线网站 | 天天色狠狠干 | 中文字幕精品一区二区三区视频 | 国产毛片毛片精品天天看 | 亚洲视频四区 | 天天狠操| 黄网站视频观看免费 | 日本亚洲欧美美色 | 插菊综合网 | 天天操天天噜 |