代碼:

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

(以上可以運行,不會報錯)

int a[4];

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

(以上會報錯)


int a = 0;

這叫初始化

int a; a = 0;

這叫賦值

雖然長得像,但完全是兩種東西。

數組只能初始化,沒辦法賦值。


定義的時候賦值叫初始化……和賦值不是一回事兒


這樣可以,先用typeof把匿名字面量轉換成數組對應類型,再memcpy。不過應該沒什麼地方用得上吧。。。

#include &
#include &

int main(void)
{
int a[3];
memcpy(a, (typeof(a)){1,2,3}, sizeof(a));

printf("%d
", a[0]);

return 0;
}

如果是結構體,連memcpy也不用,可以直接用加了typeof的匿名變數來賦值。

typeof似乎是gcc的擴展語法,gcc以外的環境不知道能不能用了。

#include &
#include &

struct {
int a;
float b;
} t;
int main(void)
{
t = (typeof(t)){1, 2.0};
printf("%f
", t.b);
return 0;
}


在modern cpp中可以後賦值的, 見: https://godbolt.org/z/N7odMG


因為C語言標準一直沒支持這麼寫,定義的時候那個叫做初始化初值,不叫賦值。C語言一致沒支持數組的直接賦值,但是支持結構體的直接賦值,所以要實在想直接賦值,可以這麼干,雖然很麻煩:

typedef struct int_array_4_
{
int a[4];
} int_array_4;

int main(int argc, char *argv[])
{
int_array_4 a;
int *a_a = (int *)a;

a = (int_array_4){{1, 2, 3, 4}};

printf("%d
", a_a[0]);

return 0;
}


數組可以通過字面量初始化

但不能通過字面量賦值

賦值必須基於索引/下標


a[4]是什麼?

int a[4];

這個語句定義了一個含 4 個 int 型元素的數組。

那請問 a 的數據類型是什麼?

int[4]

就是包含了 4 個 int 型元素的數組。

其中還可以通過對 a 解除引用(也就是 *a )來訪問 a[0] ,數組 a 的第一個元素。也就是說, a 可以看作指向 a[0] 的一個常指針。

也就只有在定義的時候, a[4] 是包含 4 個元素的數組。

a[4] = 233;

這個語句為 a[4] 這個元素賦值為 233 。就不像上面的定義是指一個有 4 個元素的數組。

a[0] 是數組 a 的第一個元素,那麼 a[4] 就是第 5 個……

等等,數組 a 不是只有 4 個元素嗎……

C 語言可不管這個。在 C 語言中, a[4] 就相當於 *(a+4) 。 a+4 是什麼?就是 a 指向的地址,往後數 4 個 int 占的位元組數,數到的地址。再一解除引用,就得到了那個地址里的數據。對 a[1] , a[2] 和 a[3] 是同樣的。 C 語言只管找地址,數組越界什麼的是不會管的。

C++ 抄 C 的時候就把這個抄過來了(怎麼能說是抄呢

是的,你在用 a[4] 的時候用上了別人家的內存。(手動滑稽)

然後是 = { 1 , 2 , 3 , 4 } 的問題。

= 是幹什麼用的?

當然是賦值用的啦。

一定義就賦值的操作,又叫做初始化。

初始化時等號右邊可以是一些奇奇怪怪的東西。

int a[4] = { 1, 2, 3, 4 };
char str[7] = "vczhnb";
struct student
{
char name[16];
int age;

} vczh = { "Victor Chen" , 666 };

每個數組或結構體只有這一次愉快賦值的機會哦!過期不候!再往後只能一個一個元素或成員的賦值了。

自己想想定義完 C 風格字元串 str 之後你又寫了句 str = "lzgnb"; 試圖修改 str 的內容。

然而這時 str 已經算是個常指針了,給一個常指針賦值你是在想桃吃。(逃

寫出 a[4] = { 1 , 2 , 3 , 4 }; 就是更NM離譜,把一個 initializer-list 賦給一個 int ?你這輩子都別想再吃桃了。(不知道 initializer-list 的請自行百度)

以上種種原因導致定義之後的數組和結構體都不能再用等號直接賦值了(直接把結構體賦給結構體還是可以的)

至於有些什麼簡便的賦值方法,其它回答已經給出,比如 memcpy() 或專門針對 C 風格字元串的 strcpy() 之類的。題主可以自己去了解一下。


cppreference上有明確的說明,見圖

而且退一萬步講,a[4]指的是數組中的一個元素,類型是int,當然不能把int數組類型賦值給int類型


不一定要在一行內賦值,你的問題有幾個

第一,你沒有理解下標a[4]是指下標為4的那個元素,但是你理解為了a這個數組,造成這個誤解可能是因為,申明數組的時候是寫a[4]。

第二,可以賦值,可以了解一下memset和memcpy兩個函數

第三,對於int a[4]的理解,等你學會了動態分配內存malloc應該會對這個問題有一個更深一點的想法


首先

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

應該相當於

int a[4];

a={1,2,3,4};

而不是a[4]={1,2,3,4}

但是這個格式仍然是不允許的。因為規定如此,這個只能用作初始化。


a[4]指的是a數組中的第5個int元素,你不能對它賦值另外一個數組。如果先聲明了需要用for或者指針來挨個賦值才能覆蓋整個數組。


語法問題有什麼糾結的?


首先你的前一段代碼也會報錯,因為你把右花括弧}打成了右方括弧]。

為什麼後一段代碼會報錯,因為a[4]是int,你卻對它賦一個不能轉換成int類型的值。

另外,a[4]是數組的第五個元素,你訪問還越界了,雖然這一般不會引發報錯。


int a[4]; // 聲明了一個變數a,變數類型為 int[4]

a[4]={1,2,3,4}; // 通過數組下標給數組元素賦值,
// a[4]是一個下標訪問表達式,
// 表達式結果是一個左值,它的類型是int,
// 把一個數組字面量賦值給int類型的變數,
// 是不可能成功的。
// 另外由於a只有4個元素,下標4越界了。


c和c++就是沒有直接提供數組的賦值語法。原因大概是c++初始化即賦值的概念出現的時候語言的作者腦子不清楚。

不排除未來會直接提供數組賦值語法。

目前對無需析構的類型的數組,進行延遲初始化的技巧有

  1. placement new的數組版本,執行的是構造語義:

int a[4];

new (a[0]) int[4] { 1, 2, 3, 4 };

2. 強轉std::array賦值,執行的是先構造臨時std::array再賦值(覆蓋)到a,對於元素為簡單類型int來說,編譯器會省略構造臨時array的步奏直接賦值到a上

((std::array&) a[0]) = {1, 2, 3, 4}

對於第二種方法保證不會出錯,不像第一種方法只能對無需析構的元素類型使用


哥們,語法搞錯了吧。定義時的中括弧是表示長度,賦值時中括弧是取下標。


int a[4]={5,6,7,8}

中4為數組長度,在這時a[4]相當於整個數組,在這時你設定整個數組為{5,6,7,8}是沒有問題的

a[4]={5,6,7,8}

中4為數組下標。首先a數組長度為4。其中所有元素下標分別為0,1,2,3。這裡的a[4]就出現了第一個問題下標越界。a中根本沒有下標為4的元素。

其次a[4]現在的意義是a數組中下標為4的元素。根據定義這個元素為int類型。而後面的{5,6,7,8}並不是一個int類型,這就是第二個問題,類型錯誤。

如果您想對初始化完成的數組進行賦值那麼只能一個一個元素賦值.


推薦閱讀:
相关文章