2012-10-11 45 views

回答

9

您發佈的代碼是無效的形式來看C語言的點。 C中任何投射的結果都是一個右值。它不能用作++的參數。運算符++需要一個左值參數。即表達式++((unsigned) x)在標準C語言中是不可編譯的。

你實際上在這種情況下,觀察什麼是GCC的「廣義左值」擴展

http://gcc.gnu.org/onlinedocs/gcc-3.4.4/gcc/Lvalues.html

每即擴展(和違反標準C),流延應用於左值產生左值。當您嘗試在結果「廣義」左值中寫入某些內容時,正在寫入的值將被轉換兩次:首先將其轉換爲顯式類型轉換指定的類型,然後將中間結果再次轉換爲接收者的類型目的。最終的結果被放入收件人對象。

例如,如果你的x

(unsigned) x = 0x100; 

將通過GCC實際解釋爲

x = (uint8_t) (unsigned) 0x100; 

x終值將是0

而這正是你的例子中發生的情況。在GCC您

++((unsigned) x) 

相當於

(unsigned) x = (unsigned) x + 1; 

後者又解釋由GCC作爲

x = (uint8_t) (unsigned) ((unsigned) x + 1); 

這就是爲什麼你在x作爲結果得到0,那就是0然後被分配到您的y

此擴展被稱爲已棄用 GCC文檔。

+0

感謝您的廣泛答覆。鍵盤只是吞下的代碼沒有任何警告,我應該用gcc自己嘗試過它... – Bart

+0

@Bart:是的...... ideone也吞下它,即使在「C99嚴格」模式。 – AnT

1

要啓動這不是有效的C代碼,我不知道你是怎麼得到它來編譯,但您的鏈接確實顯示輸出,所以我會試着解釋這一個主要假設發生了什麼依據:


我想這條線unsigned y = ++((unsigned x));第二unsigned是由編譯器下降,因此爲什麼你能夠建立。


因此,假設...

uint8_t x = 0xff; // 8 bit value, max is 255(10) or 0xFF(16) 
unsigned y = ++((unsigned)x); 

現在x已經是它的類型的最大值。你想知道爲什麼我們通過++ +1,y沒有得到0x100的價值。

x是8位,類型化它不會改變它是8位的事實。所以,當我們說:

++x 

我們遞增xx=x+1)。因此,我們有一個無符號的8位值,在最大和把它加1,現在它纏到0。所以y,將會獲得0

如果你想要這個工作,你可以這樣做:

int main(void) 
{ 
    unsigned char x = 0xFF; //I'm using char because it's 8 bit too 
    unsigned int y = 1+x; //no need to typecast, we're already unsigned 
    printf("%#x %#x\n", x, y); 
    return 0; 
} 

現在你會得到的預期值(x==0xFFy==0x100

+0

該代碼無效C,所以我不知道你是如何設法解釋的。 – Lundin

+0

@Lundin - 我正在讀這個問題,因爲「爲什麼我會在給定的鏈接上得到我輸出的結果」。輸出是0.所以OP有一些非標準的編譯器允許這個(我的假設)。從概念上講,這是我給出的解釋,爲什麼他可以編譯並獲得輸出結果?我不知道,但這似乎是一個不同的話題。 – Mike

+0

@Lundin - 既然你指出了,而且我不清楚我在想什麼,我在我的帖子中澄清了這一點。我認爲現在可以接受? – Mike

0

試試這個:

uint8_t x = 0xff; 
unsigned y = ((unsigned)x) + 1; 

它會出來,你實驗值因爲(unsigned) x現在是雙字節0x0100

現在試試這個:

uint8_t x = 0xff; 
++x; 

的周圍0xff餘套0x00值。

0

我把一些小小的透明代碼放入你的摘錄中,它解釋了一切。

#include <stdio.h> 
#include <stdint.h> // not needed 

int main(void) { 
    uint8_t x = 0xff; 
    printf("%d\n", sizeof(x)); 
    unsigned y = ++((unsigned)x); 
    printf("%d\n", sizeof(y)); 
    printf("0x%x\n", y); 
    printf("%d\n", sizeof(y)); 
    return 0; 
} 

和輸出

1  // size of x 
4  // size of y before computation 
0x100 // computed value of y from your code 
4  // size of y after computation 

注意到的第一件事是,sizeof(y)保持跨越計算不變。
從輸出,

  • uint8_t = 1字節
  • unsigned = 4字節

當你用C做一個演員,把它作爲realloc隱式調用它說:「藉此數據,我從它的塊,增加(或減少),其在內存中的大小尺寸有我想投它,然後在新的塊返回相同的數據。

而且從我方第從unsigned將有足夠的空間來適應單字節操作的計算結果。需要左值的增量operand`:

重新explainng你的代碼的字節層次的細節,

x    = 11111111       = 0xff (in a byte) 
(unsigned)x  = 00000000000000000000000011111111 = 0xff (in a word) 
++((unsigned)x) = 00000000000000000000000100000000 = 0x100 
+0

允許'++((無符號)x)的編譯器名稱是什麼? –

+0

我在OS X的llvm-gcc和RedHat發行版上的gcc上試了這個。 – iGbanam

+0

我只是嘲笑OS X的英特爾電腦附帶的vanilla gcc(GNU's),它也編譯過。 – iGbanam