回答:
はシステムに署名されているffffff
ため、char
が表示されています。Cでは、のような可変引数関数は、printf
より小さいすべての整数推進するint
にはint
。char
は整数(この場合は8ビットの符号付き整数)なので、charはint
符号拡張を介して昇格されます。
以来、c0
及び80
(8ビット整数として負の)先頭の1ビットを持っているあなたのサンプル中の他のものはないが、それらは符号拡張されています。
char int
c0 -> ffffffc0
80 -> ffffff80
61 -> 00000061
これが解決策です:
char ch = 0xC0;
printf("%x", ch & 0xff);
これにより、上位ビットがマスクされ、必要な下位8ビットのみが保持されます。
unsigned char
は、x86-64のgcc4.6では1つの命令が小さい...
x
は符号なしの型を必要とするため、これは(技術的に)未定義の動作ですが、chはintに昇格されます。正しいコードは、単にchをunsignedにキャストするか、またはキャストをunsigned charと指定子に使用しますhhx
。
printf("%x", 0)
、何も印刷されません。
printf("%.2x", 0);
描画される最小文字数を2に増やしてみてください。最大値を設定するには、を付加します。番号付き。たとえば、強制的に描画できるのは2文字だけですprintf("%2.2x", 0);
実際、intへの型変換があります。また、%hhx指定子を使用して、タイプを強制的にcharにすることもできます。
printf("%hhX", a);
ほとんどの場合、最小の長さも設定して、2番目の文字をゼロで埋める必要があります。
printf("%02hhX", a);
ISO / IEC 9899:201xは言う:
7長さ修飾子とその意味は次のとおりです。hh次のd、i、o、u、x、またはX変換指定子が、signed charまたはunsigned char引数に適用されることを指定します(引数は整数の昇格に従って昇格されます。ただし、その値は、出力前に、signed charまたはunsigned charに変換されます。またはその次
を使用hh
しprintf
て、引数がunsigned charであることを通知できます。使用0
ゼロパディングを取得し、2
2に幅を設定するx
か、X
下/大文字進文字に。
uint8_t a = 0x0a;
printf("%02hhX", a); // Prints "0A"
printf("0x%02hhx", a); // Prints "0x0a"
編集:読者が2501の主張が「正しい」形式指定子ではないという懸念がある場合は、もう一度printf
リンクを読むことをお勧めします。具体的には:
%cはint引数を期待しますが、可変個関数が呼び出されたときに整数の昇格が行われるため、charを渡しても安全です。
固定幅文字タイプ(int8_tなど)の正しい変換仕様は、ヘッダー
<cinttypes>
(C ++)または<inttypes.h>
(C)で定義されています(ただし、PRIdMAX、PRIuMAXなどは%jd、%juなどと同義です)。
符号付きと符号なしの彼のポイントについては、値は常に正であり、signed intに簡単にフィットする必要があるため、この場合は問題ではありません。とにかく、符号付き16進数形式指定子はありません。
編集2:(「いつ許可するか」が間違っている場合):
311ページ(PDFの329)で実際のC11標準を読むと、次のことがわかります。
HH:次のことを指定し
d
、i
、o
、u
、x
、またはX
変換指定が適用されるsigned char
か、unsigned char
引数(引数が整数プロモーションに従って進められているであろうが、その値に変換しなければならないsigned char
か、unsigned char
印刷する前に)。または、次のn
変換指定子がsigned char
引数へのポインターに適用されること。
inttypes.h
char
そして)[ en.cppreference.com/w/cpp/language/variadic_arguments]にunsigned char
昇格します。あなたは、あなたのプラットフォームに適合しないもののためにPRI指定子を使用する必要があります例えば- 。int
int
unsigned int
%x
intではなくunsigned intの場合は正しいです。char型とunsigned char型はintに昇格されます。さらに、uint8_tがunsigned charとして定義されている保証はありません。
おそらく、signed char配列から印刷しています。unsigned char配列から出力するか、値を0xffでマスクします(例:ar [i]&0xFF)。高(符号)ビットが設定されているため、c0値は符号拡張されています。
このようなものを試してください:
int main()
{
printf("%x %x %x %x %x %x %x %x\n",
0xC0, 0xC0, 0x61, 0x62, 0x63, 0x31, 0x32, 0x33);
}
これはこれを生成します:
$ ./foo
c0 c0 61 62 63 31 32 33
"\xc0\xc0abc123"