2013-09-16 67 views
0

C99標準說,在6.7.5.3/7以下:我可以在C99中使用數組作爲函數參數嗎?

一個參數作爲「」「類型的數組」的聲明,應調整至「」合格指針 類型「」,其中類型限定符(如果有)是在數組類型派生的[和]中指定的那些。

我的理解是:

void foo(int * arr) {} // valid 
void foo(int arr[]) {} // invalid 

然而,GCC 4.7.3會很樂意接受這兩個函數定義,即使與gcc -Wall -Werror -std=c99 -pedantic-errors編譯。由於我不是C專家,我不確定我是否可能誤解了標準的內容。

我也注意到,

size_t foo(int arr[]) { return sizeof(arr); } 

總是返回的sizeof(int *)代替數組大小,這公司我相信int arr[]作爲int *處理和gcc只是試圖讓我感覺更舒服。

有人可以解釋一下這個問題嗎?僅供參考,此問題源自this comment

+2

編譯器正在執行C99 std引用的說法:它將'[]'形式調整爲'*'形式。因此這兩者是等同的。幾乎沒有辦法將整個數組按值傳遞給C函數。您只能傳遞一個指針並在函數體內手動創建副本。例外情況是,記錄中的數組字段將在按值傳遞時與記錄一起傳遞。因此,您有時會看到一個數組字段的記錄,其中記錄僅僅是包裝數組以獲得此效果。 – Gene

+0

@Gene D'uh,我犯了一個錯誤,把這個標準的段落作爲對C程序員的指令,而不是C編譯器。愚蠢的我。 – nijansen

回答

2

無論您有效無效聲明是內部等價的,即編譯器將後者到前者。

你的函數看到的是指向數組的第一個元素的指針。

PS。另一種方法是將整個陣列推向堆棧,從時間和空間的角度來看,這將是非常低效的。

3

一些上下文:

首先,請記住,當它是不sizeof或一元&操作者的操作數,或類型「的T N元件陣列」的表達出現在上下文不是用於在聲明中初始化另一個數組的字符串文本,它將被轉換爲類型爲「指向T的指針」的表達式,其值將是數組中第一個元素的地址。

這意味着當您將一個數組參數傳遞給一個函數時,該函數將接收一個指針值作爲參數;在函數被調用之前,數組表達式被轉換爲指針類型。

這一切都很好,但爲什麼arr[]允許作爲指針聲明?我不能說這就是肯定是的原因,但我懷疑它是從C語言衍生的B語言中保留下來的。事實上,幾乎所有關於C中的數組的東西都是狡猾的或不直觀的,這是從B的緩衝中獲得的。

B是一種「無類型」語言;你沒有爲浮動,整數,文本,不管什麼類型。一切都以固定大小的單詞或「單元格」存儲,而內存被視爲一個線性單元格陣列。當你在

auto arr[10]; 

宣告乙一個陣列,編譯器會擱置10細胞陣列,然後擱置,將存儲的偏移到所述陣列的所述第一元件的額外11細胞,並額外的單元格將被綁定到變量arr。與C中一樣,B中的數組索引計算爲*(arr + i);你會將存儲在arr中的值,添加一個偏移量i,並取消引用結果。裏奇保留了大部分這些語義,除了不再爲數組的第一個元素指定存儲空間外,相反,當代碼被翻譯時,該指針值將是,從數組表達式本身計算。這就是爲什麼數組表達式轉換爲指針類型的原因,爲什麼&arrarr給出相同的值,如果不同的類型(數組的地址和數組的第一個元素的地址相同)以及爲什麼數組表達式不能分配的目標(沒有什麼可以將分配給;沒有存儲空間用於獨立於數組元素的變量)。

現在,這裏是有趣的一點;在B,你會申報了「指針」作爲

auto ptr[]; 

這不得不分配單元存儲的偏移量數組的第一個元素,並將其綁定到ptr的效果,但ptr沒點特別是任何地方;你可以指定它指向不同的位置。我懷疑這個符號是因爲幾個原因而被擱置的:

  1. 大部分在C初始版本上工作的人都熟悉它;
  2. 它強調參數代表調用者中的一個數組;

就個人而言,我更希望裏奇曾使用*到處指定三分球,但他沒有(或交替使用[]在所有情況指定一個指針,而不僅僅是一個函數參數聲明)。我通常會建議每個人都使用*表示法來表示函數參數,而不是[],因爲它更準確地表達了參數的類型,但我可以理解爲什麼人們更喜歡第二種表示法。

相關問題