成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

數組不可以直接賦值,為什么結構體中的數組卻可以?

開發 后端
在 C/C++ 語言中,數組類型的變量是不可以直接賦值的。但是如果把數組放在結構體中,然后對結構體變量進行賦值,就可以實現把其中的數組內容進行復制過去。C/C++ 只是一門高級語言,是被標準委員會從無到有設計出來的,因此我們編程時需要嚴格遵守這些規則。

[[393663]]

一、前言

在 C/C++ 語言中,數組類型的變量是不可以直接賦值的。但是如果把數組放在結構體中,然后對結構體變量進行賦值,就可以實現把其中的數組內容進行復制過去。

很多朋友對這個不是特別理解,只是強制記憶,下面我嘗試用自己的理解來描述一下,希望對你有所幫助!

二、數組的各種操作

1. 錯誤代碼

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

對于上面的賦值語句,編譯器會報錯 error: assignment to expression with array type,即:不能對一個數組類型的變量進行賦值。

那么編譯器此時是如何來解釋 a 和 b 的?下面會說到這個問題。

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

2. 利用結構體來復制數組

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

這里的賦值操作是針對結構體變量,C 語言標準允許這種行為,是合法的,變量 a 中的所有內容(也就是這個變量占用過的那一塊內存空間中的內容)會原樣的復制到變量 b 中。

3. 其他復制方式

既然不能直接對數組類型的變量進行賦值,只能尋求其他的替代方式,例如:

  1. 利用 memcpy(b, a, sizeof(int) * 5); 復制一整段內存空間中的內容;
  2. 利用 for/while 等循環語句,逐個復制數組中每一個元素: b[i] = a[i];

三、語言標準和編譯器

C/C++ 只是一門高級語言,是被標準委員會從無到有設計出來的,因此我們編程時需要嚴格遵守這些規則。

這些規則中,就包括這么一條:只有標量和結構體,才能出現在賦值操作符=的左側。

但是數組類型并不是一個標量,因此不能對結構體執行賦值操作。

理論上,如果 C/C++ 語言愿意的話,是"可以"對數組直接賦值的(那就要修改語法標準),只不過標準委員會在經過各種場景的權衡利弊之后,做出了目前這樣的規定,這是對各種考慮到的因素進行權衡之后的結果。

也就是說,目前標準中對于數組操作的方式,是利大于弊。

既然標準已經是制定成這樣的了,我們就來分析一下編譯器是如何來遵循、實現這個標準的。

1. 數組與指針的曖昧關系

很多人都這樣記憶:數組名就是數組開始地址的指針。這是不對的,或者說不嚴謹的。

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

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

對于下面這段代碼,打印結果是相同的:

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

第一個 printf 中,a 會“臨時的”代表指向第一個元素的常量指針。

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

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

2. 為什么不能對數組變量賦值

有了上面的基礎理解就好辦了,對于下面的這段代碼:

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

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

既然在一個表達式中,數組名被臨時的表示第一個元素的常量指針,那么就說明我們不能對數組名本身進行計算,例如:不能進行 a++, a-- 等操作。

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

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

3. 函數形參是數組的情況

考慮下面這個函數:

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

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

PS: 這種場景下都需要額外的傳遞一個參數,來告知元素的個數。

調用這個函數的代碼如下:

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

數組名臨時代表第一個元素的常量指針,在傳參的時候,形參 arr 的值就是數組中第一個元素的內存地址。

4. 為什么結構體中的數組可以復制

有了前面的語法標準,這個問題似乎不用再討論了~~

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

編譯器是知道一個結構體變量所占用的空間大小的,所以當復制的時候,類似于 memcpy 一樣,把一個結構體變量所占空間按照 byte to byte 的方式復制過去。

5. 參數傳遞和返回值

  1. 在調用函數時,實參到形參的傳遞;
  2. 函數執行結束后的返回值;

這兩個場景中都涉及到變量的賦值問題。

關于參數傳遞,上面已經說了:編譯器是把形參當做普通的指針類型的。

對于函數返回值來說,同樣的道理,也不能直接返回一個數組,因為它僅僅是臨時性的代表第一個元素的常量指針。

當然,可以利用結構體的可賦值特性,把數組包裹在其中,以此達到復制的效果。

五、總結

記住這兩句話:

1.數組就是數組,指針就是指針,它們各不相干。

2.在表達式中,數組名會“臨時的”表示數組中第一個元素的常量指針(前提條件:在沒有操作符sizeof 和 & 的情況下)

 

責任編輯:姜華 來源: IOT物聯網小鎮
相關推薦

2020-10-21 09:16:49

Linux開源操作系統

2023-05-09 10:05:24

HashMapNull

2015-06-25 13:29:21

2014-11-28 16:04:36

浪潮

2022-05-19 10:04:15

UIAndroid子線程

2009-01-11 10:05:44

郵件宕機摩卡

2022-02-13 20:31:26

SpringBootjarmanifests

2022-02-15 07:03:04

start 源碼run線程

2010-12-30 09:22:58

C語言 數組

2024-06-18 10:28:46

2021-07-26 05:20:47

JavaScript解構賦值數組解構

2024-07-17 11:35:31

JavaScript解構賦值

2024-09-10 15:34:18

JavaScript解構賦值

2023-11-30 08:16:19

SpringjarTomcat

2021-07-29 18:48:32

Swift iOS macOS

2009-08-13 13:03:52

C#結構體數組

2009-08-13 13:17:10

C#結構體數組

2024-04-03 09:01:34

SpringTomcat容器

2019-10-24 15:20:10

微信分享

2021-02-03 14:40:22

Python字典語言
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品一区二区三区四区 | 国产精品不卡 | 一区二区三区免费 | 久久久久久免费毛片精品 | 国产乱码精品一区二区三区忘忧草 | 欧美成人一区二区三区 | 国产高清在线 | av播播 | 婷婷在线网站 | 久久亚洲国产精品日日av夜夜 | 精品欧美一区二区三区久久久 | 色婷婷精品国产一区二区三区 | 亚洲精品视频在线观看免费 | 99在线免费观看视频 | 日韩精品一区二区三区中文在线 | 欧美视频在线观看 | 9久久精品| 国产精品国产馆在线真实露脸 | 欧美日韩国产传媒 | 亚洲 欧美 日韩 精品 | 99久久婷婷国产综合精品电影 | 国家aaa的一级看片 h片在线看 | 91传媒在线观看 | 久久久精品影院 | 韩国精品一区 | 欧美中文字幕在线观看 | 日韩和的一区二在线 | 日本在线一二 | 欧美色综合 | 久久最新| 亚洲精品久久久蜜桃网站 | 天天干b | 99在线精品视频 | 午夜电影网 | 在线黄av | 国产精品久久国产精品久久 | 色精品视频 | 亚洲精品久久久久久久久久久久久 | 九七午夜剧场福利写真 | 精品1区2区 | 在线视频中文字幕 |