1. 程式人生 > >C語言中 unsigned char 與 signed char 不同輸出格式一些認識

C語言中 unsigned char 與 signed char 不同輸出格式一些認識

首先考慮下面程式碼輸出什麼?

#include <stdio.h>

int main(void)
{

	signed char a = -1;
	unsigned char b = -1;

	printf("%%d:\n");
	printf("%d\n", a);
	printf("%d\n", b);

	printf("\n%%u:\n");
	printf("%u\n", a);
	printf("%u\n", b);

	return 0;
		
}	

%d格式下  a = -1  b = 255,%u格式下  a = 4294967295   b = 255.

下面我們進行分析為什麼會出現這種結果:

首先數字在記憶體中以他的補碼形式儲存, -1的補碼為全1,這個不會因為他被賦予變數大小或變數型別有無符號而改變。變數大小改變的是儲存此數字的位數,例如signed char 變數 -1補碼儲存在它裡面為 11111111(1位元組。) signed int 為 11111111 11111111 11111111 11111111(假設此時int為4位元組)。變數型別有無符號表示如何看待最高位。 例如 -1 賦予一個 signed char變數 。 則11111111最高位1被當為符號位。 -1被賦予一個unsigned char變數  則11111111 最高位1被當作數值位(不再當作符號位)。

此時我們來分析 signed char -1 以%d 形式輸出。 首先它以補碼形式儲存在此型別變數, 11111111 最高位被當作符號位。 因為要求以%d(十進位制有符號整數型別)輸出。

因此我們將他的補碼補到32位。 因為他為signed 型別,所以補碼補符號位。 11111111前面補24個符號位1即補碼變為FFFFFFFF。 又因為以十進位制有符號整數型別格式輸出(將這個FFFFFFFF看作一個有符號數補碼,將這個補碼以%d格式進行解釋,並輸出),所以把最高位看為符號位,即他為一個負數。 將此負數補碼轉換為原碼可得 10000000 00000000 00000000 00000001所以輸出-1.

同理分析%u  形式輸出。 補完符號位後補碼變為FFFFFFFF。 此時以無符號十進位制整數形式輸出(即把這個FFFFFFFF看做一個無符號數的補碼), 我們將他最高位看做數值位,無符號數即大於等於0數。 所以原碼即補碼 ,所以原始碼為FFFFFFFF的二進位制數值為4294967295.

接下來分析 unsigned char -1.  -1以補碼形式儲存在記憶體中的值為全1。 將他賦給一個unsigned char變數時, 為 11111111(依然是這種形式不變)。只是系統認為他的最高位不是符號位,為數值位。 此時以%d 格式輸出,先進行補碼補全。  因為此時為unsigned 所以 11111111前面補數字0而不是符號位.  補全後補碼變為 00000000 00000000 00000000 11111111 此時以%d 格式列印。 最高位為0,系統把他看做一個正數的補碼, 即原碼也是這個。 此原碼值為255.

最後,以%u形式輸出(系統認為此補碼代表一個大於等於0數,所以即使最高位為1,也被當作數值位。而不是把他當作負數)。 00000000 00000000 00000000 11111111   %u格式把最高位當作數值位。 值為255.

此程式碼可判斷你的編譯器char是什麼型別,加上一條 char c = -1; 判斷a.b.c輸出值即可。

下面程式碼是另一種問題:

#include <stdio.h>

int main(void)
{

	signed char a = 128;
	signed char b = -128;

	printf("%%d:\n");
	printf("%d\n", a);
	printf("%d\n", b);

	printf("\n%%u:\n");
	printf("%u\n", a);
	printf("%u\n", b);

	return 0;
		
}	

我們先進行分析,char變數為一個位元組,八位元位。儲存有符號數時最高位為符號位。 而128二進位制形式為10000000.

有符號數128 最高位 為 0 後八位為10000000  儲存在signed char變數中,因為此變數只有八個位元位空間, 所以儲存時被截斷為 10000000.

此時,因為為signed char型別,最高位1被解釋為符號位。

以%d形式輸出,先補全補碼,補符號位1.     11111111 11111111 11111111 10000000.  隨後,%d格式,所以他被解釋為一個負數的補碼,轉化為原碼,數值為-128.

%u格式易得值為.

signed char -128.最高位為1 後八位為100000000。 儲存時被截斷為10000000. 同理可分析,%d%u格式與128輸出相同.