C言語出力ASCIIコード128~255と符号付きchar型オーバーフローについて質問です.ここの大きな穴が分かったら記録して共有して...

2795 ワード

次のコードはWindowsコンソールから正常に出力されると文字化けします
#include
int main(){
    char a=197;
    printf("%c",a);
    return 0;
}

どうしてですか.
1.前提条件を先に説明する:C言語ではcharタイプのデフォルトは符号タイプ(範囲は-128~127)であり、もちろん符号タイプなし(unsigned char)を宣言することもできるが、これは本明細書の議論の範囲内ではない.
上記の列では、a = 197に対応する文字は ASCII には存在せず、 ASCII 0~127の文字のみを定義しているが、1バイトが0~255を表すことができることはよく知られているので、余分なバイトASCIIは使用されず、拡張符号化として使用されている.したがって,疑問符や他の文字化け記号が出力されるのは,我々のASCII符号化にはこの位置の符号化記号がないからである.
2.次に、私たちの中国語家庭版Windows 10のパソコンでは、CMDのデフォルトの符号化フォーマットは936(ANSI/OEM-簡体字中国語GBK)です.
以下の引用では、GBK符号化とASCII符号化の関係がよくわかります.
【1】ASCII:1文字あたり1 bytesを占め、バイナリで表すと最上位は0(拡張ASCIIは考慮外)でなければならないため、ASCIIは128文字【2】GB 2312:最早版の中国語コードのみを表し、1文字あたり2 bytesを占める.ASCIIと互換性があるため、この2 bytesの最上位は0ではありません(そうでなければASCIIと衝突します).GB 2312には6763の漢字と682の特殊記号が収録されており、生活で最もよく使われる漢字をすべて網羅している.【3】GBK:GB 2312は6763文字しかないので、私の中国語は博大で奥深いですが、6763文字しかありません.そこでGBKでは、GB 2312、ASCIIとの衝突(すなわち、GB 2312とASCIIとの互換性)を保証する前提の下で、1文字あたり2 bytesを占める方式で多くの漢字を符号化している.GBK符号化後、表示できる漢字は20902個に達し、中国語の句読点、部首など984個もある.注目すべきは、この20902文字には繁体字も含まれていることだ.
補足:
【4】GB 18030:しかし、GBKの2万字以上も私たちのニーズを満たすことができず、自分が見たことのない漢字をコードする必要がある可能性があります.このとき2 bytesだけでは1文字では足りないことは明らかです(2 bytesは最大65536種の組み合わせしかありませんが、ASCIIと互換性があるため、最上位は0ではなく半分の組み合わせを直接淘汰し、3万種以上の組み合わせだけでは漢字の要求を満たすことができません).このためGB 18030より多く出てくる漢字は4 bytes符号化を用いている.もちろん、GBKを互換化するために、この4バイトの上位2ビットは明らかにGBKと衝突できない(実技では後2ビットもGBKと衝突していないことが分かった).わが国が2000年と2005年にそれぞれ公布した2回のGB 18030コードのうち、2005年は2000年の基礎の上でさらに補充した.これで、GB 18030の中国語の文書はすでに7万余りの漢字があり、少数民族の文字さえ含まれている.
  • の最終的な要件は、GBK符号化フォーマットがASCII符号化フォーマットと互換性があることであり、197には対応する文字が設計されていないことである.
  • 128~255 , 、例えばアメリカの符号化規格:437(OEM-アメリカ)に変更すると、SCIIコードの128-255を表示する特殊文字が正常に表示されます.
  • 最も簡単な方法は、プログラムに以下のヘッダファイルとコマンドを加えることで、コードページのデフォルトの表示方法を変更することができます:
  • #include
    #include
    int main(){
        SetConsoleOutputCP(437);
        char a=197,b=198;
        printf("%c %c",a,b);
    }
    
  • 以上の修正により、197と198に対応する文字を正常に表示することができ、それぞれはRと╞であり、もちろんこれは1つの符号化フォーマットの下で、もう1つの符号化フォーマットを交換すれば、また異なる可能性がある.

  • 3.それ以外のC言語では、charが符号型である場合、すなわち、表現範囲は-128~127である.符号付きcharタイプでは、0~127と-128~-1の2つのセグメントが記憶上2つの異なるセグメントに分けられる.
    じっしん
    対応する符号表示
    -128
    1000 0000
    -127
    1000 0001
    -126
    1000 0010
    -125
    1000 0011


    -2
    1111 1110
    -1
    1111 1111
    0
    0000 0000
    1
    0000 0001


    127
    0111 1111
    これがコンピュータで採用されている補符号表現法であり,バイナリ最高位はシンボルビットを表し,1は負数,0は整数である.
    以上のように、コンピュータにおけるデータの記憶形式は、符号を補完する形で記憶され、C言語において符号を有するchar型であり、その負の数段と正の数段のメモリにおける記憶形式は異なる(最上位)が、いずれも を満たす.
    不足があれば、指摘を歓迎します.