2014-10-29 175 views
19

我已經懷疑關於以下的代碼:陣列初始化用C

int main() 
{ 
    int array1 = {1,2,3,4,5}; //error in c++ , warning in c 
    int array2[] = {1,2,3,4,5}; 
    int array3[5] = {1,2,3,4,5}; 
} 

這段代碼在c++但不是在c給出在第3行一個錯誤?

我知道array1實際上是一個intarray2array3是數組,那麼爲什麼沒有一個c編譯器顯示一個錯誤,但只是一個警告:「在標量初始化多餘元素」

是否有使用這樣的定義,爲什麼它在c有效?

+2

你使用哪個編譯器作爲VS 2012將它視爲錯誤 – 2014-10-29 10:25:44

+21

C與C++不同。 – 2014-10-29 10:26:57

+2

哪條線準確給出錯誤?第4行是'array2'的聲明,但唯一有問題的行是'array1'的行。 – 2014-10-29 10:27:46

回答

26

這是無效的C.請參閱C11 6.7。9:

No initializer shall attempt to provide a value for an object not contained within the entity being initialized.

我猜你正在使用gcc。然後,如果你希望你的程序表現爲嚴格的標準C,編譯成這樣:

gcc -std=c11 -pedantic-errors 

error: excess elements in scalar initializer

+4

這違反了約束條件,即使沒有'-pedantic-errors',gcc也可以根據需要正確地發佈診斷信息,而對於ISO C而言,它足夠嚴格。實現不需要拒絕代碼。 – 2014-10-29 11:12:20

+2

@BlueMoon這是因爲標準中沒有警告和錯誤等事情。對於程序員來說,錯誤會更好。 – Lundin 2014-10-29 11:57:10

15

不是在C中有效。它只是對代碼檢查較少。這是未定義的行爲。

來源:C11 draft N1570; 6.7.9 Initialisation

Constraints
2 No initializer shall attempt to provide a value for an object not contained within the entity being initialized.
3 The type of the entity to be initialized shall be an array of unknown size or a complete object type that is not a variable length array type.

絕對打破約束2.是一種int一個完整的對象類型

附件J.2(未定義行爲):

The initializer for a scalar is neither a single expression nor a single expression enclosed in braces (6.7.9).

額外:
@詹姆斯甘孜:

prog.c:4:12: error: expected identifier or ‘(’ before numeric constant 
    int i = 1,2,3,4,5; 
      ^

你可以做到這一點,但你需要使它一個表達式:

int i = (1,2,3,4,5); //need parenthesis, evaluates to 5, values 1-4 thrown away. 

編制與int初始alised與initalizer列表產生一個警告(海合會):

prog.c:5:2: warning: excess elements in scalar initializer [enabled by default] 
    int j = {1,2,3,4,5}; 
^

但現在看來,編譯器是足夠聰明,只是初始化int而不是以下的內存。 demo

+2

不確定違反約束會導致未定義的行爲。 C標準是陳述還是暗示? – 2014-10-29 11:19:56

+0

但是'1,2,3,4,5''可以被解釋爲一個初始化器。 ('int x = 1,2,3,4,5;'絕對是合法的。) – 2014-10-29 11:57:36

+2

但是'{1,2,3,4,5}!= 1,2,3,4,5'。前者是一個初始化列表,後者與逗號運算符有5個不同的值。我認爲這適用於:'標量的初始化方法既不是單個表達式也不是單個表達式(6.7.9).'請糾正我錯誤 – Baldrickk 2014-10-29 12:00:27

2

初始化在C/C數組++正確的做法是:

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

這裏的方括號實際上告訴編譯器,這是一個數組,一組在您的案件數字。在這種初始化中,不需要指定數組的長度。編譯器會知道。

第二種方法是定義一個數組,後初始化:

int array3[5]; 
int *array = new int[5]; 

在這種情況下,你需要告訴編譯器的陣列將是什麼規模。而且,在第二種情況下,您需要手動刪除內存。

+0

這不是問題的答案。 – 2014-10-29 13:07:47

11

這是因爲按照C規範有效。從C11節6.7.9(初始化)

引用:

Syntax

1 initializer: 
    assignment-expression 
    { initializer-list } 
    { initializer-list , } 

那麼初始化器可以是直接表達(assignment-expression以上),或初始化的大括號圍列表。標準中該部分的約束不限制「正常」(非數組或非指針)變量。

這使您可以編寫例如

int a = { 1 }; 
+0

這是這個答案列表中最相關的(甚至是正確的)答案。 – bitcell 2014-10-29 10:34:04

+0

我的C編譯器確實接受單個值「{1}」,但是提到OP的「array1」錯誤C2078:太多初始值設定項「。 – 2014-10-29 10:38:46

+0

C繼續給我留下了深刻的印象 – 2014-10-29 10:42:48

1

C是低級許可語言。它允許影響指向int的指針。

int array1 = {1,2,3,4,5}; 

編輯:

我應該寫的蠢事之前根據不同的編譯器都進行了測試。

這被MSVC(2008)的錯誤拒絕。

gcc和clang都發出警告excess elements in scalar initializer,只是影響1到a

+0

編譯器如何知道它是一個'char'數組?爲什麼不是'整數'? '是任何人的雙重身份?對不起,你的回答是無稽之談。初始化器列表在'C'中沒有類型。 – GreenScape 2014-10-29 13:00:24

+1

@GreenScape:你是對的!我已經更新了我的答案... – 2014-10-29 13:30:05

+0

你可以做一些令人討厭的reinterpret轉換來使指針成爲'int',儘管我懷疑不是初始化。+1進行虛假陳述,然後從中學習。 – imallett 2014-10-29 18:12:17

3

像其他人一樣,我認爲你想知道關於該行:

int array1 = {1,2,3,4,5}; 

在這種情況下,有C和C++之間沒有什麼區別;這條線在兩種語言中都可以說是合法的,但這並不意味着你可能會這麼想。在C和C++中都有一個聲明,如果類型是標量類型(int是),那麼{...}的內容必須是單個表達式。並且1,2,3,4,5可以解釋爲單個表達式(使用逗號運算符);例如:

int array1 = 1, 2, 3, 4, 5; 

顯然是合法的。

這有點曖昧,但是,因爲在這兩種語言的語法這種類型的初始化,使,標點符號,而不是運營商。所以這是一個解釋的問題;是內容必須是單個表達式對語法(這會導致逗號變成運算符)的約束或對評估指定語法結果的約束的聲明。我直觀的感覺是,第二個是意圖,並且該聲明應該導致錯誤。但區別不在於C和C++之間,而在於編譯器的作者解釋標準的方式。

編輯:

重讀靠近一點:在C++標準,它明確地說,

If T is a scalar type, then a declaration of the form

 
    T x = { a }; 

is equivalent to

 
    T x = a; 

哪個不留下太多的蠕動室:在C++中,聲明似乎明確的法律;只有在C有些模棱兩可的地方。

+5

我不認爲這裏存在歧義,語法根本不允許'''成爲逗號運算符。如果我們看一下'6.7.8'爲initialzer語法包括'分配,expression'不能讓我們到一個逗號操作符不'()'...所以我們可以做'{(1,2,3,4 ,5)}'但這有可疑的用處。 – 2014-10-29 12:04:12

+0

@ShafikYaghmour這是一個很好的觀點。但是這似乎意味着'int a = 1,2,3;'也是非法的。不過,我確信我已經使用了它(或類似的東西)。或者,也許我總是把它放在括號內;我不確定。 (我使用括號來講清楚只有一個表達所涉及的讀卡器。) – 2014-10-29 12:12:31

+0

'的GCC -std = C99 = -pedantic拒絕errors'編譯'INT A = 1,2;'。您的建議的標準的讀出也將導致有問題的,例如,'INT A = 1,B = 2;'在塊範圍時B'的'文件範圍聲明是可見的或用語句表達式的GCC擴展(GCC擴展旨在不與ISO C衝突)。 – mafso 2014-10-29 17:15:36

2

正如你的編譯器所說,這對於C來說也是不正確的。這裏需要注意的是,如果出現這種「約束違規」(官方術語),編譯器可能會產生一個診斷(您的編譯器會這樣做)並繼續。

這就是爲什麼一般你應該確保你的代碼編譯沒有任何診斷任何。