2012-07-22 87 views
0
#include <stdio.h> 
#include <stdlib.h> 

int main(int argc, char **argv){ 
    char i = -128; 
    int j = i; 
    printf("%d %u\n", j, j); 
    return 0; 
} 

結果是-128 4294967168怎樣的printf知道符號擴展後打印出什麼

什麼,我認爲是

i: 10000000 

和賦值運算符後,執行符號擴展

j: 11111111 11111111 11111111 10000000 

我想問的是如何printf("%d",j)知道要打印-128絕對t使用

最後一個字節?怎麼運行的?

Thx!

+0

你真的會打印'-127'嗎? – 2012-07-22 19:32:10

+0

@ Jonathan Leffler是的,我真的明白了。 – 2012-07-22 19:33:29

+0

非常有趣;你在運行什麼硬件?當我使用'-fsigned-char'在Mac OS X 10.7.4上進行編譯時,我得到了'-128 4294967168'(這兩者與你報告的內容相差1);當我用'-funsigned-char'編譯時,我得到'128 128'。分配給int時,我沒有看到編譯器將分配給'char'的-128'轉換爲'-127'的合法方式。 – 2012-07-22 19:41:35

回答

6

我想問的是printf(「%d」,j)知道如何打印-128只是使用最後一個字節?

它沒有。它被告知打印一個簽名的int,所以它從堆棧中獲取適當數量的字節(通常爲4),並將該位模式解釋爲簽名爲int

當您將負charint變量,如int j = i;這裏發生的事情是不是真的符號擴展,但 - 因爲所有值的char可以代表也可表示爲int - 一個保值轉換,chari被轉換爲具有相同值的int。在現在最普遍的補碼機器上,也是在補碼中,保值轉換恰好與符號擴展一致,但是如果代表是符號和幅度,轉換會有所不同。

由於-128不能表示爲1的補碼或符號和幅度中的帶符號八位整數,我們來看看將-127轉換爲32位帶符號整數時發生的位模式變化同一種表示方法:

兩個補:

10000001 -> 11111111 11111111 11111111 10000001 

的補:

10000000 -> 11111111 11111111 11111111 10000000 

登錄和幅度:

11111111 -> 10000000 00000000 00000000 01111111 
+1

'j'已經是'int'了,不是嗎? – 2012-07-22 19:33:30

+0

哦,對。被「只使用最後一個字節?」所迷惑。 – 2012-07-22 19:36:47

+0

@ Liang-YuPan假設標準二進制補碼和八位(帶符號)char,32位int,char i = -128;的位模式是10000000或十六進制0x80, 'int'-128的位模式,不管它是通過從char轉換還是以其他方式獲得,都在上面的假設'0xFFFFFF80'(爲了簡潔起見,十六進制)之下。所以當'printf'打印一個有符號整數('%d')並找到該位模式時,它會打印-128。當它將該位模式解釋爲無符號整數('%u')時,該值爲'2^32 - 128 = 4294967168'。 – 2012-07-22 20:08:19

2

它只是打印未簽名的版本-128(在這種情況下爲int)。

1

您強制投看到一個整數的第一個字節:

char j = -128; 
printf("%d", (char) j); 

看到第二個字節爲十進制,你強制投之一:

printf("%d", *(((char *) &j) + 1)); 

的最後一個字節一個整數:

printf("%d", *(((char *) &j) + 3)); 
1

您的程序正在調用未定義的行爲通過將錯誤的類型傳遞給printf%u需要unsigned參數,但您通過了(簽名)intprintf不「知道該做什麼」,因爲它不需要特別做任何事情;你可以自由地做任何事情,因爲你調用了UB。

1

這是一個簡單的測試程序,可以幫助您瞭解正在發生的事情。需要注意的是它使用C99長度修改hh,這意味着:

hh用於指定後續dioux,或X轉換說明適用於 signed charunsigned char參數(該參數將有 根據整數升級推廣,但其打印前的價值應爲 轉換爲signed charunsigned char);或者 後面的n轉換說明符適用於指向signed char 參數的指針。

這可能會幫助您瞭解類型的處理方式。

#include <stdio.h> 
#include <limits.h> 

static void print_value(signed char sc, unsigned char uc, /*plain*/ char pc) 
{ 
    int j1 = sc; 
    int j2 = uc; 
    int j3 = pc; 
    printf("%-9s %4hhd %4hhu %4d 0x%hhX %10u\n", "Signed:", j1, j1, j1, j1, j1); 
    printf("%-9s %4hhd %4hhu %4d 0x%hhX %10u\n", "Unsigned:", j2, j2, j2, j2, j2); 
    printf("%-9s %4hhd %4hhu %4d 0x%hhX %10u\n", "Plain:", j3, j3, j3, j3, j3); 
} 

static void check_value(int i) 
{ 
     signed char sc = i; 
     unsigned char uc = i; 
     /*plain*/ char pc = i; 
     print_value(sc, uc, pc); 
} 

int main(void) 
{ 
    for (int i = 0; i <= 3; i++) 
     check_value(i); 
    for (int i = SCHAR_MAX - 3; i <= SCHAR_MAX+3; i++) 
     check_value(i); 
    for (int i = UCHAR_MAX - 3; i <= UCHAR_MAX; i++) 
     check_value(i); 
    return 0; 
} 

-fsigned-char編譯(所以 '純' char是簽名型),輸出是:

Signed:  0 0 0 0x0   0 
Unsigned:  0 0 0 0x0   0 
Plain:  0 0 0 0x0   0 
Signed:  1 1 1 0x1   1 
Unsigned:  1 1 1 0x1   1 
Plain:  1 1 1 0x1   1 
Signed:  2 2 2 0x2   2 
Unsigned:  2 2 2 0x2   2 
Plain:  2 2 2 0x2   2 
Signed:  3 3 3 0x3   3 
Unsigned:  3 3 3 0x3   3 
Plain:  3 3 3 0x3   3 
Signed:  124 124 124 0x7C  124 
Unsigned: 124 124 124 0x7C  124 
Plain:  124 124 124 0x7C  124 
Signed:  125 125 125 0x7D  125 
Unsigned: 125 125 125 0x7D  125 
Plain:  125 125 125 0x7D  125 
Signed:  126 126 126 0x7E  126 
Unsigned: 126 126 126 0x7E  126 
Plain:  126 126 126 0x7E  126 
Signed:  127 127 127 0x7F  127 
Unsigned: 127 127 127 0x7F  127 
Plain:  127 127 127 0x7F  127 
Signed: -128 128 -128 0x80 4294967168 
Unsigned: -128 128 128 0x80  128 
Plain:  -128 128 -128 0x80 4294967168 
Signed: -127 129 -127 0x81 4294967169 
Unsigned: -127 129 129 0x81  129 
Plain:  -127 129 -127 0x81 4294967169 
Signed: -126 130 -126 0x82 4294967170 
Unsigned: -126 130 130 0x82  130 
Plain:  -126 130 -126 0x82 4294967170 
Signed:  -4 252 -4 0xFC 4294967292 
Unsigned: -4 252 252 0xFC  252 
Plain:  -4 252 -4 0xFC 4294967292 
Signed:  -3 253 -3 0xFD 4294967293 
Unsigned: -3 253 253 0xFD  253 
Plain:  -3 253 -3 0xFD 4294967293 
Signed:  -2 254 -2 0xFE 4294967294 
Unsigned: -2 254 254 0xFE  254 
Plain:  -2 254 -2 0xFE 4294967294 
Signed:  -1 255 -1 0xFF 4294967295 
Unsigned: -1 255 255 0xFF  255 
Plain:  -1 255 -1 0xFF 4294967295 

與-funsigned炭編譯(so 'plain' char`是一個無符號類型),輸出是:

Signed:  0 0 0 0x0   0 
Unsigned:  0 0 0 0x0   0 
Plain:  0 0 0 0x0   0 
Signed:  1 1 1 0x1   1 
Unsigned:  1 1 1 0x1   1 
Plain:  1 1 1 0x1   1 
Signed:  2 2 2 0x2   2 
Unsigned:  2 2 2 0x2   2 
Plain:  2 2 2 0x2   2 
Signed:  3 3 3 0x3   3 
Unsigned:  3 3 3 0x3   3 
Plain:  3 3 3 0x3   3 
Signed:  124 124 124 0x7C  124 
Unsigned: 124 124 124 0x7C  124 
Plain:  124 124 124 0x7C  124 
Signed:  125 125 125 0x7D  125 
Unsigned: 125 125 125 0x7D  125 
Plain:  125 125 125 0x7D  125 
Signed:  126 126 126 0x7E  126 
Unsigned: 126 126 126 0x7E  126 
Plain:  126 126 126 0x7E  126 
Signed:  127 127 127 0x7F  127 
Unsigned: 127 127 127 0x7F  127 
Plain:  127 127 127 0x7F  127 
Signed: -128 128 -128 0x80 4294967168 
Unsigned: -128 128 128 0x80  128 
Plain:  -128 128 128 0x80  128 
Signed: -127 129 -127 0x81 4294967169 
Unsigned: -127 129 129 0x81  129 
Plain:  -127 129 129 0x81  129 
Signed: -126 130 -126 0x82 4294967170 
Unsigned: -126 130 130 0x82  130 
Plain:  -126 130 130 0x82  130 
Signed:  -4 252 -4 0xFC 4294967292 
Unsigned: -4 252 252 0xFC  252 
Plain:  -4 252 252 0xFC  252 
Signed:  -3 253 -3 0xFD 4294967293 
Unsigned: -3 253 253 0xFD  253 
Plain:  -3 253 253 0xFD  253 
Signed:  -2 254 -2 0xFE 4294967294 
Unsigned: -2 254 254 0xFE  254 
Plain:  -2 254 254 0xFE  254 
Signed:  -1 255 -1 0xFF 4294967295 
Unsigned: -1 255 255 0xFF  255 
Plain:  -1 255 255 0xFF  255 

在Mac OS X 10.7.4上使用GCC 4.7.1編譯(但在平臺上使用標準C庫)。