CとC++のタイプ変換

2465 ワード

新しい部門に来てから手配された最初のコードに関する仕事はlintを修正することです.これはプロジェクトのコードスタイルを熟知する絶好の方法です.その間、最もやりにくい問題も最も多い問題は、タイプ変換の問題であり、どのような整数オーバーフローや記号の損失などである.
最近、C専門家のプログラミングを見ていて、ANSI Cが規定した算術変換規則について話していて、私の心の中の疑問を解いたと言っています.
セクション6.2.1.1文字と整数(整数アップグレード)
char、shortまたはint型ビットセグメント(bit-field)は、intまたはunsigned intを必要とする式で使用できる、シンボルなし変形、および列挙タイプを含む.intがソースタイプのすべての値を完全に表すことができる場合(ANSI規定、short<=int<=longであるが、具体的には大きくても規定されていない)、そのメタタイプの値はintに変換され、そうでなければunsigned intに変換される.これを整形アップグレードと呼ぶ.
第6.2.1.5節普通算術変換
定義:多くのオペランドタイプが算術タイプの両目演算子は変換を開始し、同様の方法で結果タイプを生成します.通常のタイプを生成することを目的とし、演算結果のタイプでもあります.このモードを「通常算術変換」と呼ぶ.
ルール:
浮動小数点数
  • まず、1つのオペランドがlong doubleである場合、もう1つはlong doubleに変換される.
  • の次に、1つのオペランドがdoubleである場合、もう1つはdoubleに変換される.
  • 再び、floatなら..

  • 整形
  • オペランドの1つのタイプがunsigned longである場合、もう1つはunsigned longに変換される.(unsigned longが最大で選ばれなかった).
  • オペランドの1つがlongであり、もう1つのオペランドのタイプがunsigned intである場合.
  • longがunsigned intのすべての値を完全に表現できる場合、unsigned intはlongに変換されます.
  • longがunsigned intのすべての値を完全に表現できない場合、両方のオペランドはunsigned longに変換される.(もっと長いタイプではだめなので、符号なしに回します)
  • のうちの1つのオペランドAタイプがlongであり、もう1つのオペランドBタイプがint以下である場合、Bはlongに変換される.
  • オペランドAタイプの1つがunsigned intであり、もう1つのオペランドBタイプがint以下である場合、Bはunsigned intに変換される.
  • その他の場合、両方のオペランドはintに変換されます.

  • まとめ
    通俗的な言葉で上記のルールをまとめます.
    演算を実行すると、オペランドのタイプが異なると変換されます.データ型は一般的に浮動小数点精度が高く、長さが長い方向に変換され、整形術はsignedに変換しても情報が失われない場合はsignedに変換され、そうでなければunsignedに変換される.
    例を見て
    #include 
    
    int array[] = {1, 2, 3, 4, 5, 6, 7};
    #define TOTAL_ELEMENTS (sizeof(array)/sizeof(array[0]))
    
    
    int main() {
        int d = -1;
        int x = 0;
    
        if (d <= TOTAL_ELEMENTS - 2) {
            printf("array len more than 2
    "); } return 0; }

    まずコードの本来の意味はarrayの長さが2以上であるか否かを判断し,printf可能なコンテンツが印刷されることを望んでいる.でも上のルールから見るとTOTAL_ELEMENTSの結果はunsigned int(sizeof()の戻り値のため)であり、dが-1からunsigned intに変換され、それは巨大な正の整数になる.したがって、式の結果は偽です.
    このコードと変種は普段の作業コードの中でほとんどあちこちにあるので、当社のプログラミング規範に基づいて、いくつかの点に注意する必要があります.
  • 汎用仕様では、6.1関数マクロの代わりにできるだけ関数を使用し、できるだけ関数またはインライン関数を使用することを推奨します.
  • セキュリティ仕様規則4.1整数間の演算は、オーバーフロー、反転、0を除くことなく厳格にチェックする必要があります.
  • セキュリティ仕様規則4.2整数表現は、より大きなタイプの間でこのようなより大きなタイプで彼を評価しなければならないように比較または付与される.
  • セキュリティ仕様規則4.3は、符号付き整数のオペレータ演算を禁止する.(例外あり)
  • もう一つ規範では見つからなかったのですが、個人的には意味があると思います.
    演算前(比較、加減算など)に、2つのオペランドのタイプが一致することを手動で確認します.Cを書く以上、複雑で儚いコンパイラの潜在的なルールに依存するのではなく、すべてをあなた自身の掌握の中に置いてください.