【C言語】奇妙な引き算
if((1-2)<0U)

奇妙な引き算

warning: comparison of unsigned expression in ‘< 0’ is always false

警告:符号無しは負値にならない
[-Wtype-limits]


■符号なし変数の引き算結果をゼロと比較するのは避けよう

ここでは数学とは異なる、
C言語の暗黙の型変換の不思議な動きをご紹介します。


■(1-2)<0 が成立(uint8_t型)

#include    <stdio.h>
int main(void) {
    unsigned char u1 = 1;
    unsigned char u2 = 2;
    if((u1 - u2) < 0)   
        puts("数学と同じく、引き算の結果は負値");
    else                
        puts("到達不能");
}

1-2が負値になり数学と同じ結果となります。


■(1-2)<0 が不成立(uint32_t型)

#include    <stdio.h>
int main(void) {
    unsigned int u1 = 1;
    unsigned int u2 = 2;
    if((u1 - u2) < 0)   
        puts("到達不能");
    else                
        puts("直観と違うがここに来る");
}

1-2が負値にならず数学と異なる結果となります。

C言語の型変換規則は非常に難解です。
符号無しの引き算を行った場合
直観とは異なる結果になる場合があります。
型変換規則を完全に理解する前に、
型変換規則は難解である事を理解しましょう。


■(1-2)<0U が不成立(int32_t型)

warning: comparison of unsigned expression in ‘< 0’ is always false

警告: ‘< 0’ と符号なし式の比較は常に偽
[-Wtype-limits]

#include    <stdio.h>
#define     ZERO 0U //マクロでU接尾子が見えない
int main(void) {
    signed int s1 = 1;
    signed int s2 = 2;
    if((s1 - s2) < ZERO)   
        puts("到達不能");
    else                
        puts("数学と違うがここに来る");
}

1-2が負値にならず直観と異なる結果となります。

C言語の型変換規則は非常に難解です。
符号付きの引き算と0Uを比較した場合
直観とは異なる結果になる場合があります。


このコードの場合0Uと比較しているので
演算子の両辺が符号無し型となります。
このため (s1 – s2) は引き算の結果に関係無く
0以上の値となります。

参考:

INT30-C. 符号無し整数の演算結果がラップアラウンドしないようにする