溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

為什么數(shù)組不可以直接賦值

發(fā)布時(shí)間:2021-10-13 11:52:57 來源:億速云 閱讀:2838 作者:iii 欄目:編程語言

這篇文章主要介紹“為什么數(shù)組不可以直接賦值”,在日常操作中,相信很多人在為什么數(shù)組不可以直接賦值問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”為什么數(shù)組不可以直接賦值”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!

為什么數(shù)組不可以直接賦值

一、前言

在 C/C++  語言中,數(shù)組類型的變量是不可以直接賦值的。但是如果把數(shù)組放在結(jié)構(gòu)體中,然后對(duì)結(jié)構(gòu)體變量進(jìn)行賦值,就可以實(shí)現(xiàn)把其中的數(shù)組內(nèi)容進(jìn)行復(fù)制過去。

二、數(shù)組的各種操作

1. 錯(cuò)誤代碼

int a[5] = {1, 2, 3, 4, 5}; int b[5]; b = a;

對(duì)于上面的賦值語句,編譯器會(huì)報(bào)錯(cuò) error: assignment to expression with array  type,即:不能對(duì)一個(gè)數(shù)組類型的變量進(jìn)行賦值。

那么編譯器此時(shí)是如何來解釋 a 和 b 的?下面會(huì)說到這個(gè)問題。

有一個(gè)地方提一下:第一條語句中的 = 操作,不是賦值,而是初始化。C/C++ 語法規(guī)定在定義變量的時(shí)候,是可以使用 操作符 =  來進(jìn)行初始化操作的。

2. 利用結(jié)構(gòu)體來復(fù)制數(shù)組

typedef struct {     int arr[5]; } array_wrap;  array_wrap a = {{1, 2, 3, 4, 5}}; array_wrap b; b = a;

這里的賦值操作是針對(duì)結(jié)構(gòu)體變量,C 語言標(biāo)準(zhǔn)允許這種行為,是合法的,變量 a  中的所有內(nèi)容(也就是這個(gè)變量占用過的那一塊內(nèi)存空間中的內(nèi)容)會(huì)原樣的復(fù)制到變量 b 中。

3. 其他復(fù)制方式

既然不能直接對(duì)數(shù)組類型的變量進(jìn)行賦值,只能尋求其他的替代方式,例如:

  1. 鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)

  2. 利用 memcpy(b, a, sizeof(int) * 5); 復(fù)制一整段內(nèi)存空間中的內(nèi)容;

  3. 利用 for/while 等循環(huán)語句,逐個(gè)復(fù)制數(shù)組中每一個(gè)元素: b[i] = a[i];

三、語言標(biāo)準(zhǔn)和編譯器

C/C++ 只是一門高級(jí)語言,是被標(biāo)準(zhǔn)委員會(huì)從無到有設(shè)計(jì)出來的,因此我們編程時(shí)需要嚴(yán)格遵守這些規(guī)則。

這些規(guī)則中,就包括這么一條:只有標(biāo)量和結(jié)構(gòu)體,才能出現(xiàn)在賦值操作符=的左側(cè)。

但是數(shù)組類型并不是一個(gè)標(biāo)量,因此不能對(duì)結(jié)構(gòu)體執(zhí)行賦值操作。

理論上,如果 C/C++  語言愿意的話,是"可以"對(duì)數(shù)組直接賦值的(那就要修改語法標(biāo)準(zhǔn)),只不過標(biāo)準(zhǔn)委員會(huì)在經(jīng)過各種場(chǎng)景的權(quán)衡利弊之后,做出了目前這樣的規(guī)定,這是對(duì)各種考慮到的因素進(jìn)行權(quán)衡之后的結(jié)果。

也就是說,目前標(biāo)準(zhǔn)中對(duì)于數(shù)組操作的方式,是利大于弊。

既然標(biāo)準(zhǔn)已經(jīng)是制定成這樣的了,我們就來分析一下編譯器是如何來遵循、實(shí)現(xiàn)這個(gè)標(biāo)準(zhǔn)的。

1. 數(shù)組與指針的曖昧關(guān)系

很多人都這樣記憶:數(shù)組名就是數(shù)組開始地址的指針。這是不對(duì)的,或者說不嚴(yán)謹(jǐn)?shù)摹?/p>

在 C/C++ 中,數(shù)組就是數(shù)組,指針就是指針。數(shù)組在內(nèi)存中有確定的空間(每個(gè)元素的大小 x 元素個(gè)數(shù))。

只不過在表達(dá)式中,數(shù)組名會(huì)“臨時(shí)的”表示數(shù)組中第一個(gè)元素的常量指針(前提條件:在沒有操作符 sizeof 和 & 的情況下)。

對(duì)于下面這段代碼,打印結(jié)果是相同的:

int a[5] = {1, 2, 3, 4, 5}; printf("a = %p \n", a); printf("&a = %p \n", &a);

第一個(gè) printf 中,a 會(huì)“臨時(shí)的”代表指向第一個(gè)元素的常量指針。

第二個(gè) printf 中,a 就表示一個(gè)數(shù)組,與指針沒有半毛錢的關(guān)系,前面加上取地址符  &,就表示獲取這個(gè)數(shù)組所在的地址,這個(gè)地址與第一個(gè)元素的地址是重合的。

注意:代碼在被編譯成二進(jìn)制文件之后,沒有任何變量的概念,全部是用地址來“傳遞” C/C++ 代碼中的變量。

2. 為什么不能對(duì)數(shù)組變量賦值

有了上面的基礎(chǔ)理解就好辦了,對(duì)于下面的這段代碼:

int a[5] = {1, 2, 3, 4, 5}; int b[5]; b = a;

在賦值語句 b = a 中,左側(cè)的 b 是一個(gè)數(shù)組類型,右側(cè)的 a  被編譯器“臨時(shí)的”代表第一個(gè)元素的常量指針,但是數(shù)組不是一個(gè)標(biāo)量,不可以放在賦值運(yùn)算符=的左側(cè),因此編譯器就抱怨:非法!

既然在一個(gè)表達(dá)式中,數(shù)組名被臨時(shí)的表示第一個(gè)元素的常量指針,那么就說明我們不能對(duì)數(shù)組名本身進(jìn)行計(jì)算,例如:不能進(jìn)行 a++, a-- 等操作。

例如:下面這的遍歷方式是非法的:

int a[5] = {1, 2, 3, 4, 5}; for (int i = 0; i < 5; i++) {     // 常量指針,不可以進(jìn)行遞增操作     printf("a[%d] = %d \n", i, *a++); }

3. 函數(shù)形參是數(shù)組的情況

考慮下面這個(gè)函數(shù):

void func(int arr[5])  {     for (int i = 0; i < 5; ++i)      {         printf(*arr++);  // 合法!     } }

形參 arr 在形式上好像是一個(gè)數(shù)組,實(shí)際上被編譯器當(dāng)做指針,也就是相當(dāng)于:void func(int *arr),因此,在 printf  打印語句中,可以對(duì) arr 進(jìn)行遞增操作。

PS: 這種場(chǎng)景下都需要額外的傳遞一個(gè)參數(shù),來告知元素的個(gè)數(shù)。

調(diào)用這個(gè)函數(shù)的代碼如下:

int a[5] = {1, 2, 3, 4, 5}; fun(a);

數(shù)組名臨時(shí)代表第一個(gè)元素的常量指針,在傳參的時(shí)候,形參 arr 的值就是數(shù)組中第一個(gè)元素的內(nèi)存地址。

4. 為什么結(jié)構(gòu)體中的數(shù)組可以復(fù)制

有了前面的語法標(biāo)準(zhǔn),這個(gè)問題似乎不用再討論了~~

賦值的目的是什么?就是讓一塊內(nèi)存空間的內(nèi)容,與另一塊內(nèi)存空間中的內(nèi)容完全相同。如果想要完成復(fù)制操作,那么就需要知道這塊內(nèi)存空間的大小。

編譯器是知道一個(gè)結(jié)構(gòu)體變量所占用的空間大小的,所以當(dāng)復(fù)制的時(shí)候,類似于 memcpy 一樣,把一個(gè)結(jié)構(gòu)體變量所占空間按照 byte to byte  的方式復(fù)制過去。

5. 參數(shù)傳遞和返回值

  1. 鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)

  2. 在調(diào)用函數(shù)時(shí),實(shí)參到形參的傳遞;

  3. 函數(shù)執(zhí)行結(jié)束后的返回值;

這兩個(gè)場(chǎng)景中都涉及到變量的賦值問題。

關(guān)于參數(shù)傳遞,上面已經(jīng)說了:編譯器是把形參當(dāng)做普通的指針類型的。

對(duì)于函數(shù)返回值來說,同樣的道理,也不能直接返回一個(gè)數(shù)組,因?yàn)樗鼉H僅是臨時(shí)性的代表第一個(gè)元素的常量指針。

當(dāng)然,可以利用結(jié)構(gòu)體的可賦值特性,把數(shù)組包裹在其中,以此達(dá)到復(fù)制的效果。

到此,關(guān)于“為什么數(shù)組不可以直接賦值”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

c++
AI