簡體   English   中英

為什么不存在數組賦值操作但是C語言中的結構賦值呢?

[英]Why array assignment operation doesn't exist but structure assignment does in C language?

int a[10];
int b[10];

a = b; // illegal

typedef struct {
    int real;
    int imag;
    } complex;

complex c,d;
c = d; //legal

[我意識到a和b是第一種情況下的地址,但是第二種情況下的符號]

對於歷史信息,這可能很有趣: http//cm.bell-labs.com/who/dmr/chist.html

在B中,聲明一個數組會為數組留出內存,就像C一樣,但是為變量提供的名稱用於定義指向數組的指針。 Ritchie在C中對此進行了更改,因此名稱“是”數組,但在使用時可以衰減為指針:

在今天的C中存活的規則是,數組類型的值在表達式中出現時轉換為指向構成數組的第一個對象的指針。

盡管語言的語義存在潛在的變化,但本發明使大多數現有的B代碼能夠繼續工作。 為數組名稱分配新值以調整其原點的少數程序 - 可能在B和BCPL中,在C中無意義 - 很容易修復。

如果在那個早期階段,Ritchie已經定義a = b來復制數組,那么他試圖從B端口移植到C的代碼就不那么容易修復了。 正如他所定義的那樣,該代碼會產生錯誤,他可以修復它。 如果他讓C復制數組,那么他就會默默地改變代碼的含義來復制數組,而不是重新設置用於訪問數組的名稱。

還有一個問題,“為什么自40年以來沒有添加這個功能”,但我認為這就是為什么它不是從那里開始的。 這本來是努力實現的,並且這種努力實際上會使C的早期版本變得更糟 ,從稍微難以將B和BCPL代碼移植到C.所以當然Ritchie沒有這樣做。

因為C表示你不能,它說“可修改的左值是一個沒有數組類型的左值,沒有不完整的類型”,所以無法分配數組。

此外,當您在值上下文中使用數組的名稱時,如a = b; ,名稱ab均表示&a[0]&b[0] 通常稱為數組“衰減”到指針。

但是,數組不是指針,因此嘗試使用指針分配數組是沒有意義的。

主要原因當然是標准。 在賦值運算符約束上,它說:

(C99,6.5.16p2)“賦值運算符應具有可修改的左值作為其左操作數”

它將可修改的左值定義為

(C99,6.3.2.1p1)“可修改的左值是一個沒有數組類型的左值,[...]”。

因此不允許分配給數組。

但主要原因是歷史原因,因為陣列副本被認為不適合硬件(舊的PDP系統)。 在C的第一個版本中也不是這樣,也不允許分配結構類型對象。 它后來被添加到語言中,但是對於數組而言,需要更改該語言的許多部分以允許分配給數組。

首先要理解的是數組不是指針。 閱讀comp.lang.c FAQ的第6部分。 我會等。

...

OK完成? 不,回去看看整件事。

...

十分感謝。

一般來說,C中的數組是二等公民。 有數組類型,數組對象,甚至數組值,但數組幾乎總是通過指向其元素的指針來操作。

這需要程序員多做一些工作(正如您所見,您不能只分配數組),但它也為您提供了更大的靈活性。 處理數組的程序通常需要處理不同大小的數組,甚至是在執行時間之前無法確定的大小。 即使允許數組賦值,10個int的數組和20個int的數組也是不同且不兼容的類型。 如果你有一個固定大小的數組,就像在你的問題中的代碼那樣,通常只有一些元素當前是相關的; 你可能有一個10元素的數組,但你目前只使用前5個元素。 逐個元素處理這樣的數組使得更容易處理當前活動的元素(您必須跟蹤自己的事物)。

另一方面,對於結構,在定義類型時確定成員的數量和類型。 不能像通過數組一樣推進指針遍歷結構的成員,因為成員通常具有不同的類型。 數組和結構是不同的東西,它們具有對它們有意義的不同操作集。

該語言中有一些規則試圖使其更容易實現,即:

  • 在大多數但不是所有上下文中,數組表達式被隱式轉換為指向數組第一個元素的指針。 例外情況是:
    • 當數組表達式是& (地址)運算符的操作數時;
    • 當它是sizeof的操作數時;
    • 當它是初始化程序中的字符串文字時,用於初始化數組對象。)
  • 聲明的數組參數,如int func(char s[]); 調整為指針參數: int func(char *s);

(人們可能會爭辯說這些規則引起的混淆比他們預防的更多,但這就是定義語言的方式。)

現在我認為語言可以定義,或者可以重新定義,以便在有意義的情況下允許數組賦值:

int a[10];
int b[10];
/* ... */
a = b; /* Why not? */.

也許這樣的改變甚至可以在不破壞現有代碼的情況下進行。 但是這需要針對數組到指針轉換規則的另一種特殊情況。 它只適用於像ab這樣的固定大小的數組,盡管它們在入門編程練習中很常見,但在生產代碼中並不常見。

數組名稱是一個const指針,因此您無法更改它指向的內容。

假設你的意思是最后一行的c = d是合法的,它只是將一個非const變量復制到另一個非const變量,這是完全合法的。

a實際上是數組第一個元素的“指針”,它是一個常量“指針”,所以你試圖分配一個l-“指針”。

你可以通過以下方式實現你想做的事情:

struct arraystruct
{
  int t[10];
};


struct arraystruct a,b;

a=b;

編輯:我忘了提到有一些例外,其中數組不應被視為指針:

- 你可以使用sizeof(數組)但你不能使用sizeof(指針)

-array of literal string

-a和&a是一樣的

那是因為您使用的數組類型是所謂的靜態數組,即。 它的內存在堆棧上。 如果你使用動態數組(帶指針)你的任務是合法的(但是內存泄漏是可能的)。 這將是一個淺層副本。

另請參閱C ++中的靜態數組與動態數組

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM