例如這個代碼:
#include<stdio.h>
void main()
{
char c1,c2;
c1 = 197;
c2 = 198;
printf("c1 = %c,c2 = %c\n",c1,c2 );
printf("c1 = %d,c2 = %d",c1,c2);
return;
}
回傳的是[
c1 = ?c2 = ?
c1 = -59,c2 = -58
想問一下回傳的%d值是怎么計算的,觀察的結果是
比如c1轉2進制:11000101 然后首位1保留 其他的取補碼 1 0111010
這樣的結果計算出來是終端回傳的結果,
想知道這樣對嗎?為什么會這么計算?
uj5u.com熱心網友回復:
百度“負數、補碼”%c問號的原因是因為找不到對應的ASCII字符
uj5u.com熱心網友回復:
我知道%c是找不到字符 就是不是很理解他那個%d輸出的原理
uj5u.com熱心網友回復:
這是一個簡單而又復雜的問題。首先, %c 和 %d 都要求對應的變參是 int 型別。唯一不同的是,%c 是將這個 int 型別的變參轉換為 unsigned char 型別的字符,然后予以顯示,而 %d 則是將它轉換為有符號十進制格式的數字字符予以顯示。
其次,程式是沒有問題的。盡管傳入的變參是 char 型別的,但依照默認實參轉換(default argument conversion)的規則,它是被轉換為 int 型別之后傳遞給 printf 的。
最后,對于 printf 來說, %c 是將傳入的值按 int 型別(的長度)取出,然后轉換(縮小)為 unsigned char 型別(的長度),將它視為字符編碼,然后列印這個字符; %d 是將傳入的值按 int 型別(的長度)取出,拆分數位并轉換為有符號十進制數字字符列印輸出。這里的關鍵是, %d 要求這個轉換程序必須區分數值的正負。這很好辦,只需要判斷其二進制形式的最高位(符號位)就可以了:為0是正數,為1是負數。然而,在197和198這兩個數值的二進制形式中,符號位似乎并不是1。這就回到了開始:在將 char 型別的值轉換為 int 型別并傳遞給 printf 時,是如何轉換的?再往前,兩個常量197和198的型別都是 int ,將它們賦給變數 c1 和 c2 時,需要從 int 轉換為 char ,這個轉換程序又是怎樣的?
這就涉及到數值轉換規則。首先,將一個整數型別的值轉換為另一個除_Bool之外的整數型別時,如果這個值能夠用新型別來表示,則轉換后的值不變。
來看
char c1, c2;
c1 = 197;
c2 = 198;
在這里,如果 char 等價于 unsigned char ,那么,在主流的機器上,它可以表示的數值范圍是 0到255,所以能夠容納,且 printf 不可能列印兩個負值。顯然,在樓主的環境下,char實際上是signed char。在主流的機器上,它可以表示的數值范圍是-127到+128,故無法表示 197 和 198 ,需要轉換。
但是,如果新型別是有符號的并且無法表示這個值,轉換的結果要依賴于具體的編譯器,甚至可能觸發信號機制。即,C語言沒有規定如何轉換。
在很多平臺上(顯然包括樓主所在的機器環境),是直接把長度為 int 的 197 截斷為 char 型別的長度。所以,最終它表示有符號數-59。
uj5u.com熱心網友回復:
您好,非常感謝您的回復,我使用的編譯器是VS2012。我是一個C語言的初學者,我對您的回復還有一些疑問,在您的回復中說到“在197和198這兩個數值的二進制形式中,符號位似乎并不是1。”197 -->11000101 198 --> 11000110 直接轉化成二進制的首位是否會直接成為符號位呢?煩請您幫忙把197到-59的程序詳細說一下嗎?
uj5u.com熱心網友回復:
對,我這兩句話沒說明白。
賦給 c1 和 c2 的值來自于常量 197 和 198 ,這兩個常量的型別是 int 。所以,它們的最高位不是1,而是0。即,如果 int 型別的長度是 32 位,則 197 的二進制形式為 00000000000000000000000011000101 。把它截斷為 char 型別的長度時,如果 char 型別的長度是 8,則截斷后是 11000101 。
uj5u.com熱心網友回復:
這是一個簡單而又復雜的問題。
首先, %c 和 %d 都要求對應的變參是 int 型別。唯一不同的是,%c 是將這個 int 型別的變參轉換為 unsigned char 型別的字符,然后予以顯示,而 %d 則是將它轉換為有符號十進制格式的數字字符予以顯示。
其次,程式是沒有問題的。盡管傳入的變參是 char 型別的,但依照默認實參轉換(default argument conversion)的規則,它是被轉換為 int 型別之后傳遞給 printf 的。
最后,對于 printf 來說, %c 是將傳入的值按 int 型別(的長度)取出,然后轉換(縮小)為 unsigned char 型別(的長度),將它視為字符編碼,然后列印這個字符; %d 是將傳入的值按 int 型別(的長度)取出,拆分數位并轉換為有符號十進制數字字符列印輸出。這里的關鍵是, %d 要求這個轉換程序必須區分數值的正負。這很好辦,只需要判斷其二進制形式的最高位(符號位)就可以了:為0是正數,為1是負數。然而,在197和198這兩個數值的二進制形式中,符號位似乎并不是1。這就回到了開始:在將 char 型別的值轉換為 int 型別并傳遞給 printf 時,是如何轉換的?再往前,兩個常量197和198的型別都是 int ,將它們賦給變數 c1 和 c2 時,需要從 int 轉換為 char ,這個轉換程序又是怎樣的?
這就涉及到數值轉換規則。首先,將一個整數型別的值轉換為另一個除_Bool之外的整數型別時,如果這個值能夠用新型別來表示,則轉換后的值不變。
來看
char c1, c2;
c1 = 197;
c2 = 198;
在這里,如果 char 等價于 unsigned char ,那么,在主流的機器上,它可以表示的數值范圍是 0到255,所以能夠容納,且 printf 不可能列印兩個負值。顯然,在樓主的環境下,char實際上是signed char。在主流的機器上,它可以表示的數值范圍是-127到+128,故無法表示 197 和 198 ,需要轉換。
但是,如果新型別是有符號的并且無法表示這個值,轉換的結果要依賴于具體的編譯器,甚至可能觸發信號機制。即,C語言沒有規定如何轉換。
在很多平臺上(顯然包括樓主所在的機器環境),是直接把長度為 int 的 197 截斷為 char 型別的長度。所以,最終它表示有符號數-59。
您好,非常感謝您的回復,我使用的編譯器是VS2012。我是一個C語言的初學者,我對您的回復還有一些疑問,在您的回復中說到“在197和198這兩個數值的二進制形式中,符號位似乎并不是1。”197 -->11000101 198 --> 11000110 直接轉化成二進制的首位是否會直接成為符號位呢?煩請您幫忙把197到-59的程序詳細說一下嗎?
對,我這兩句話沒說明白。
賦給 c1 和 c2 的值來自于常量 197 和 198 ,這兩個常量的型別是 int 。所以,它們的最高位不是1,而是0。即,如果 int 型別的長度是 32 位,則 197 的二進制形式為 00000000000000000000000011000101 。把它截斷為 char 型別的長度時,如果 char 型別的長度是 8,則截斷后是 11000101 。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/281783.html
標籤:C語言
上一篇:這不就正常的解法嗎?為什么總是部分正確。找了好久不知道哪里錯了,大佬看看
下一篇:大佬來看看這個代碼
