2012-03-22 53 views
7

我只是偶然發現了這讓我吃驚行爲:在初始化中使用新聲明的變量(int x = x + 1)?

當寫:

int x = x+1; 
在C/C++

- 程序(或甚至更復雜的表達式涉及到新創建的變量x)我的gcc /克+ +編譯沒有錯誤。在上面的情況中,X之後是1。請注意,前一個聲明中沒有變量x的範圍。

所以我想知道這是否是正確的行爲(甚至可能在某些情況下是有用的)與一般我的gcc版本或GCC或只是一個解析器特徵模擬。

BTW:下不起作用:

int x++; 
+0

我相信X是過得去的gcc初始化爲0,但你不能依賴這種行爲,因爲該標準不要求爲。它可能會在一些系統中導致垃圾。 – vidit 2012-03-22 10:09:22

+0

@EdHeal:沒有我沒有啓用警告,也沒有啓用--ansi,但都沒有改變情況(沒有發出警告) – 2012-03-22 10:56:04

+1

有一個相關的,合法的(但不尋常的)用法:'Node simpleGraph = Node(&simpleGraph) ;'創建一個節點與自身週期性鏈接的圖。或者甚至更大,'int x = sizeof(x);'。 – MSalters 2012-03-22 12:08:26

回答

16

隨着表達:

int x = x + 1; 

變量x開始存在於=標誌,這就是爲什麼你可以在右側使用它。通過「成立」,我的意思是存在變量,但尚未由初始化部分賦值。但是,除非您使用靜態存儲持續時間(例如,函數外部)初始化變量,否則它是未定義的行爲,因爲存在的x具有任意值。

C++ 03有這樣一段話:

申報的名點立即爲它的完整說明符(第8條)後,和它的初始化(如果有的話)之前...

實施例:
int x = 12;
{ int x = x; }
這裏第二個x初始化與它自己的(不確定的)值。

第二種情況幾乎與你的問題一樣。

+0

「成立」似乎有點模糊。我想它已經在'='之前聲明瞭,否則編譯器會抱怨使用未知的標識符。但是初始化確實發生在'='處。 – hirschhornsalz 2012-03-22 10:17:44

+0

@drhirsch,我不認爲它含糊不清,我在標準中加入了這一點來說明這一點。 – paxdiablo 2012-03-22 10:28:13

+0

我在評論中的第二句話是無稽之談(或非常糟糕的措詞)。我指的是用作「聲明點」的短語「成立」。它可以被理解爲「初始化點」,這將是錯誤的。 – hirschhornsalz 2012-03-22 11:07:55

8

它不是,它是未定義行爲

您使用的是未初始化的變量 - x。你得到純粹的運氣1,任何事情都可能發生。

僅供參考,以MSVS我得到一個警告:

警告1個警告C4700:未初始化的局部變量 '我' 用

此外,在運行時,我得到一個異常,那麼這絕對不安全。

3

在第一種情況下,您只需使用已存在於變量所在內存位置的值。在你的情況下,這似乎是零,但它可以是任何東西。使用這樣的結構是災難性的,並且很難在未來找到缺陷。

對於第二種情況,這只是一個語法錯誤。你不能混合一個表達式和一個像這樣的變量聲明。

5
int x = x + 1; 

基本上

int x; 
x = x + 1; 

你剛剛被幸運x有0。

int x++; 

但是在C++中,在解析器級別是不可能的!以前可能會被解析,但語義錯誤。第二個甚至不能被解析。

-1

這是未定義的行爲,編譯器至少應該發出警告。嘗試使用g++ -ansi ...進行編譯。第二個例子只是一個語法錯誤。

+0

-ansi不會改變情況:) – 2012-03-22 10:56:45

3

變量從「=」上,所以它是有效的,並且當它是全局定義的,它被初始化爲零,所以在這種情況下,它被定義的行爲,在其他的變量被unintialized作爲這樣定義的仍然是單元化的(但是增加了1)。
注意它仍然不是很理智或有用的代碼。

0

3.3.1聲明1聲明瞭名稱的點的點立即是其完整的說明符(第8節)之後和其 初始化之前(如果有的話),不同之處如下所述。 [例如:int x = 12; {x} {x = x; }這裏第二個x用它自己的 (不確定)值進行初始化。例如末端]

上述狀態所以,應該有不確定的值,你是幸運的以1

1

您的代碼有兩個possiblities:

  1. 如果x是一個局部變量,你具有未定義的行爲,因爲您在生命週期開始之前使用對象的值。
  2. 如果x具有靜態或線程本地的壽命,它是預先初始化爲零,而你的靜態初始化將可靠地將它設置爲1。這是明確的。

您也不妨讀一讀my answer that covers related cases, including variables of other types, and variables which are written to before their initialization is completed