Comparaison entre caractères non signés et signés

J’essaie de comparer un int non signé avec un caractère signé comme ceci:

int main(){ unsigned int x = 9; signed char y = -1; x < y ? printf("s") : printf("g"); return 0; } 

Je m’attendais à ce que le rapport qualité / prix soit “g”. Au lieu de cela, c’est “s”. Quel type de conversion est fait ici?

    La section 6.3.1.8 , Conversions arithmétiques usuelles, de la section C99 détaille les conversions entières implicites.

    Si les deux opérandes ont le même type, aucune conversion supplémentaire n’est nécessaire.

    Cela ne compte pas car ils sont de types différents.

    Sinon, si les deux opérandes ont des types entiers signés ou que les deux ont des types entiers non signés, l’opérande ayant le type de rang de conversion de nombre entier inférieur est converti en type de l’opérande avec le rang le plus élevé.

    Cela ne compte pas puisque l’un est signé, l’autre non signé.

    Sinon, si l’opérande qui a un type entier non signé a un rang supérieur ou égal au rang du type de l’autre opérande, l’opérande avec le type entier signé est converti au type de l’opérande avec le type entier non signé.

    Bingo x a un rang plus élevé que y donc y est promu en unsigned int . Cela signifie qu’il se transforme de -1 en UINT_MAX , nettement supérieur à 9.

    Le rest des règles ne s’applique pas puisque nous avons trouvé notre correspondance mais je les inclurai pour plus de détails:

    Sinon, si le type de l’opérande avec le type entier signé peut représenter toutes les valeurs du type de l’opérande avec le type entier non signé, l’opérande avec le type entier non signé est converti en type de l’opérande avec le type entier signé.

    Sinon, les deux opérandes sont convertis en un type entier non signé correspondant au type de l’opérande avec un type entier signé.


    Les rangs pertinents à cette question sont indiqués ci-dessous. Tous les rangs sont détaillés dans la section C99, section 6.3.1.1 , Booléen, caractère et nombres entiers, afin que vous puissiez vous y référer pour plus de détails.

    Le rang de long long int doit être supérieur au rang de long int , qui doit être supérieur au rang de int , qui doit être supérieur au rang de short int , qui doit être supérieur au rang de signed char .

    Le rang du caractère doit être égal au rang des caractères signed char et unsigned char .

    Mon hypothèse est que y est promu en unsigned int qui devient une grande valeur (en raison du wrapping). D’où la condition est remplie.

    Ran le code suivant:

     int main(){ unsigned int x = 9; signed char y = -1; printf("%u\n", (unsigned int)y); x < (unsigned int)y ? printf("s") : printf("g"); return 0; } 

    La sortie est:

     4294967295
     s
    

    Après une casting, y prend une très grande valeur. C'est pourquoi la sortie est s.

    Le caractère est promu en unsigned int, avec une valeur MAX_UINT supérieure à 9.

    Reportez-vous au commentaire de caf dans le lien ci-dessous: Lorsque vous convertissez un nombre en dehors de la plage en un type non signé, celui-ci passe à la plage en ajoutant ou en soustrayant plusieurs fois la valeur maximale du type –

    C: Converti signé en non signé

    Dans ce cas, UINT_MAX + 1, qui correspond à 4294967296 sur votre plate-forme, est ajouté à -1 pour donner 4294967295.