【C言語】
0xFFFFffffが-1になり -1が255になる 暗黙の型変換とは?

0xffffffffとは

warning: comparison of integer expressions of different signedness: ‘signed char’ and ‘unsigned int’

警告:符号の異なる整数式の比較
[-Wsign-compare]


■0xFFFFffffと-1は等しいか?

#include    <stdio.h>
int main(void) {
    if(-1 == 0xFFFFffff)    puts("同じ");
    else                    puts("違う");
    signed char c = -1 ;
    if(c == 0xFFFFffff)     puts("同じ");
    else                    puts("違う");
    if(c == 0xFFFFffffU)    puts("同じ");
    else                    puts("違う");

    printf("-1=%x\n",-1);
    printf("0xFFFFffff=%d\n",0xFFFFffff);
    printf("0xFFFFffff=%u\n",0xFFFFffff);
}

型変換は難解なので
正解できる人は非常に少ないです。

標準ヘッダ limits.h の最大値、最小値を
無視した値の代入や比較は
理解不能なコードになるので止めましょう。

●LP64での実行結果

同じ
同じ
同じ
-1=ffffffff
0xFFFFffff=-1
0xFFFFffff=4294967295

■unsigned charに-1を代入すると?

warning: implicit conversion changes signedness: ‘int’ to ‘unsigned char’

警告:暗黙の型変換:int から符号無しchar
[-Wsign-conversion]

#include    <stdio.h>
int     main(void) {
    unsigned char   uc = 255;
    printf("%d\n",uc); 
    
    uc = -1;
    printf("%d\n",uc);
    
    uc = (unsigned char)-1;
    printf("%d\n",uc);
}

unsigned char で表現可能な値は通常0~255で、-1は表現できません。※正確にはコンパイラから提供されているlimits.hを参照してください。
表現できない-1を無理やり代入してコンパイラから警告されたらキャストで逃げるのは止めましょう。
255を表現したかったのか
-1を表現したかったのか分からなくなります。

LP64での実行結果

255
255
255

■signed charに255を代入すると?

warning: implicit conversion from ‘int’ to ‘signed char’ changes value from 255 to -1

警告:暗黙の型変換:int から符号付きchar
[-Wconstant-conversion]

#include    <stdio.h>
int main(void) {
    signed char   sc; 
    sc = -1;
    printf("%d\n",sc);
    
    sc = 255;               
    printf("%d\n",sc);
    
    sc = (signed char)255;  
    printf("%d\n",sc);
}

標準ヘッダ limits.h の値を無視して無理やり値設定し
コンパイラが警告を出すと、
キャストして警告を黙らせるプログラマは多くいますが
limits.h を無視した値設定は止めましょう。

LP64での実行結果

-1
-1
-1

参考:

CWE-194: Unexpected Sign Extension

if(0xFFFFffff >= 0)の結果は?

#include <stdio.h>
#include <string.h>
#include <stdint.h>
int     main(void){
    if(0xFFFFffff   == -1)          
        printf("等しい %dと%d\n",0xFFFFffff,-1);
    
    if(0xFFFFffff   == 4294967295)  
        printf("等しい %uと%u\n",0xFFFFffff,4294967295U);

    int32_t     s = -1 ;
    uint32_t    u = 4294967295;
    if(memcmp(&s,&u,sizeof(s)) == 0)
        printf("等しい %dと%u\n",s,u);

    if(0xFFFFffff >= 0) puts("0以上");
    else                puts("0未満");
}

●LP64での実行結果

/a.out
等しい -1と-1
等しい 4294967295と4294967295
等しい -1と4294967295
0以上

■0xFFFFffffと-1が等しくなる理由

・0xFFFFffffは32bitで表現できる
最大の正の数です。
・0xFFFFffffも、-1も、4294967295も
メモリ中のビットパターンは同じです
(32bit全部のビットが立っている)
・if(0xFFFFffff == -1)のような
符号無し(0xFFFFffff)と符号付き(-1)の比較は
符号付き-1のほうが符号無しに拡張され
双方同じ符号無しになってから比較されます。
このため0xFFFFffffと -1は等しくなります。