2012-06-06 65 views
6

我用C有這樣的程序:輸出這個程序在C中的解釋?

int main(int argc, char *argv[]) 
{ 

    int i=300; 
    char *ptr = &i; 
    *++ptr=2; 
    printf("%d",i); 
    return 0; 
} 

輸出是556的小端。

我試圖瞭解輸出。這是我的解釋。

問題是威爾的回答仍處於大端機器一樣嗎?

I = 300; => I = 100101100 //在字格式的二進制=> BB的Hb 0001 00101100其中B =字節並在存儲器中的Hb =半字節

(A)=>(假定它是小端))

0x12345678 - 1100 - 0010 (Is this correct for little endian) 

0x12345679 - 0001 - 0000 

0x1234567a - 0000 - 0000 

0x1234567b - 0000 - 0000 

0x1234567c - 下intezer的位置(PTR的位置++或PTR + 1,其中的ptr是intezer指針PTR的類型爲int =>做++ PTR它將由4字節(大小的INT)遞增)

(B)我們做char * ptr =&i;如果在執行++ ptr時它將跳轉到位置 - > 0x12345679(它具有0001 - 0000) (p)將會變爲類型char =>在執行++ ptr時它將增加1字節(char的大小) 現在我們正在做 ++ PTR = 2 => 0x12345679將由2 => 0x12345679將具有00 * 10 **被覆蓋 - 0000而不是000 * * - 0000

所以新記憶的內容將是這樣的:

(C)

0x12345678 - 1100 - 0010 

0x12345679 - 0010 - 0000 

0x1234567a - 0000 - 0000 

0x1234567b - 0000 - 0000 

這相當於=> B B的Hb 0010 00101100其中B =字節和Hb =半字節

是我的推理正確的嗎?是否有此任何其它短方法? RGDS, 多愁善感

+2

[_void main_](http://users.aber.ac.uk/auj/voidmain.cgi)? – gliderkite

+4

我相信這種行爲沒有很好的定義,因爲int的大小不能保證是4字節。 –

回答

8

在小端的32位系統中,INT 3000x012c)是典型地存儲(*)作爲4個連續字節,第一最低:2C 01 00 00。當你增加以前是int指針&i的字符指針時,你指向該序列的第二個字節,並將其設置爲2將產生序列2C 02 00 00 - 當返回到int時,該序列爲0x22c或556 。

(至於你的位序列的瞭解......這似乎有點過了。字節序影響字節順序的記憶,字節是最小的可尋址單元。字節中的位沒有得到反轉;低位字節將是2C00101100)無論系統是小端還是大端(即使系統反轉了一個字節的位,它會再次反轉它們以將它們呈現給您一個數字,所以你不會注意到有什麼不同)。最大的區別就是太大了e該字節出現在序列中。唯一的地方命令很重要,是在硬件和驅動程序等您可以接收少於一個字節在一次)。

在大端系統中,int通常由(*)表示字節序列00 00 01 2C(與字節順序中的小端表示不同 - 最高字節先出現)。你還在修改序列的第二個字節,但...做00 02 01 2C,它作爲一個int 0x02012c或131372.

(*)許多事情都在這裏發揮作用,包括補(幾乎所有的系統都使用這些日子......但C不需要它),sizeof(int)的值,對齊/填充以及系統是真正的大或小端還是半端實現。這是爲什麼使用更大類型的字節時經常會導致未定義或特定於實現的行爲的一個重要組成部分。

+0

「當你增加以前是int指針'&i'的字符指針時,你指向該序列的第二個字節[。]」如果你不小心,指針算術真的是一件棘手的小事情。 – JAB

3

這是您的int

int i = 300;  

而這正是存儲器包含在&i2c 01 00 00 下一條指令你的i地址分配給ptr,然後你移動到下一個字節++ptr並將其值更改爲2

char *ptr = &i; 
*++ptr = 2; 

所以,現在的存儲器包含:2c 02 00 00(即556)。 不同的是,在中i地址的big-endian system你會看到00 00 01 2C,後變:00 02 01 2C

即使一個int的內部rappresentation是實現定義

對於有符號的整數類型,所述對象表示的比特必須 可以分爲三組:值的比特,填充比特,和標誌 位。不需要任何填充位;有符號的字符不應該有任何填充位 。應該只有一個符號位。 是一個值位的每個位的值應與對應的無符號類型的對象 中的同一位具有相同的值(如果有符號類型中有值位,並且無符號類型中有N,則M≤N )。 如果符號位爲零,則不會影響結果值。如果 的符號位是1,則應該按照以下方式在 之一中修改該值: - 符號位0的相應值被取消 (符號和量值); - 符號位的值 - (2M)(2的 補碼); - 符號位的值爲 - (2M - 1)(其中' 補碼)。這些適用的是實現定義的,因爲 是符號位1和所有值位爲零(前兩個爲 ),還是符號位和所有值位1(用於' 互補)的值)是陷阱表示還是正常值。在符號和幅度以及1的補碼 的情況下,如果該表示是 是正常值,則稱其爲負零。

+0

問題是大endian會發生什麼。 –

3

這是實現定義的。根據標準,int的內部表示是未知的,所以你所做的不是可移植的。參見C標準中的第6.2.6.2節。

但是,由於大多數實現使用signed int的二進制補碼錶示,所以endianness會影響cHaos答案中所述的結果。

1

我喜歡實驗,這就是擁有PowerPC G5的原因。

stacktest.c:

int main(int argc, char *argv[]) 
{ 
    int i=300; 
    char *ptr = &i; 
    *++ptr=2; 
    /* Added the Hex dump */ 
    printf("%d or %x\n",i, i); 
    return 0; 
} 

生成命令:

powerpc-apple-darwin9-gcc-4.2.1 -o stacktest stacktest.c 

輸出:

131372 or 2012c 

簡歷:王超的答案是完整的,如果你還有疑問在這裏是實驗證據。