簡體   English   中英

C:為什么可以通過值(而不是數組)傳遞(到函數)結構?

[英]C: Why can you pass (to a function) a struct by value, but not an array?

其背后的任何歷史或邏輯原因?


說明:當您將數組傳遞給C語言中的函數時,實際上實際上僅將指針傳遞給了數組。 但是,在傳遞結構時,可以傳遞該結構的副本或指針。

//this:
int function(int array[10])
// is equivalent to this:
int function(int *array)
//and they both pass a pointer

//but this:
int function(struct tag name)
//passes a struct by value, where as this:
int function(struct tag *name)
//passes a pointer to it.

為什么會有所不同?

在原始K&R中,您無法按值傳遞結構。 那是語法錯誤。 由於許多編譯器供應商將其作為擴展提供,因此按值傳遞最終進入了標准。

為什么要限制,為什么要進化? C語言開發的機器很小。 段大小通常為64 KB。 記憶是寶貴的,那么為什么只要傳遞地址就復制一些內容? 在堆棧上復制64字節結構一個錯誤,甚至可能不是用戶想要的。

到1990年代中期,這已不再是事實。 32位尋址和4 MB或更大的RAM是常見的。 限制是一個障礙,並導致了一些復雜性,因為如果沒有const ,則可以修改引用傳遞的結構,這可能是不經意的。

為什么不對數組做同樣的事情? 沒有需求。 眾所周知,數組和指針在C中緊密相關。 C標准庫在很大程度上取決於通過引用傳遞,請考慮使用memsetstrcpy 通過值傳遞結構意味着僅在調用時刪除& ,而通過值傳遞數組將需要添加新的語法。 例如, by value提供C語法的編譯器供應商會被會議嘲笑。

int function(int array[10])int function(int *array)由於6.7.5.3函數聲明符(包括原型)而相同http://www.open-std.org/JTC1/SC22/wg14/ www / docs / n1124.pdf第118頁)

7參數聲明為“類型數組”應調整為“類型的合格指針”,其中類型限定符(如果有)是在數組類型派生的[和]中指定的那些。 如果關鍵字static也出現在數組類型派生的[和]中,則對於函數的每次調用,對應的實際參數的值應提供對數組第一個元素的訪問,該元素至少具有指定數量的元素通過大小表達

當然,您可以按值傳遞數組。 您需要做的就是將其包裝在struct 但這僅在數組具有確定(且不可變)大小的情況下有效。 您可以在結構中包含大小不確定的數組,但結果類型不完整,只能用作指針的目標。

這可能和我們要解釋的情況差不多。 作為參數傳遞的絕大多數數組的大小不是固定的,即使有意按值傳遞它們也是不可能的,這也是不可能的。

函數的衰減類似(但不同)。 函數不能作為參數傳遞,只能作為函數指針傳遞。 由於顯式地編寫&每次您想引用一個函數都會很繁瑣,因此語言會為您處理它。

總體而言,存在以下形式的問題:“為什么這種語言不像這種語言?” 只能回答“因為它就是這樣”。

兩個函數聲明中的類型都不同-

struct tag  /* and */ struct tag *

一個是結構變量,而另一個是結構指針。

您可以對結構進行類似操作-

int function(struct tag name[])  /*--> int function(struct tag *name)  */

以上這些是等效的。

結構體用於聲明具有原始數據類型(如int,float,long(或結構體的結構)等)的數據類型。它們應保存其中的一些,例如,學生的結構體將包含id,name,rollno,subjects ,等等。 因此,大多數struct元素最多最多包含10-20個字段(在邏輯情況下),因此,當您將struct傳遞給函數時,它必須復制大約40-100個字節。 復制該結構變量。 數組的大小可能很大,並且用於存儲相同類型的信息。 在整數的情況下,它們的大小可以為10 ^ 7,因此,如果我們實現一種語言來復制整個數組以進行函數調用,則可能必須復制(10 ^ 7)* 4個字節,這是一個巨大的數目,將嚴重影響性能。並且典型的數組大小是10 ^ 4到10 ^ 6,這仍然很多。 但是,如果您創建int(或任何其他數組)數組的結構,則可以將其作為該數組的副本傳遞給函數。 例如

#include<stdio.h>

typedef struct {
    int arr[10];
}arrayStruct;

void change(arrayStruct a){
    a.arr[2]=5;
}
int main(){
    arrayStruct a;
    for(int i=0;i<10;i++){
        a.arr[i]=i;
    }
    printf("Before:\n");
    for(int i=0;i<10;i++){
        printf("%d ",a.arr[i]);
    }
    change(a);
    printf("\nAfter:\n");
    for(int i=0;i<10;i++){
        printf("%d ",a.arr[i]);
    }
    return 0;
}

在大多數情況下不會這樣做,但是在需要傳遞數組但又不想更改其內容但又需要對其副本進行某種更改並想要返回該副本的情況下,這種情況很少發生數組的結構,並從結構的返回類型的函數返回它們,例如

arrayStruct returnChange(arrayStruct a){
    a.arr[2]=332;
    return a;
}

暫無
暫無

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

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