• [^] # Re: Comportement non défini en C

    Posté par . En réponse au message deux char pour faire un short. Évalué à 1.

    L'opération "a << b" est indéfini en C si b est plus grand que le nombre de bits de a.

    Plus grand ou égal. D'où un problème (en C du moins).

    Mais il y a autre chose. Si le type char est signé (en C, c'est possible, et même courant. En C++, à voir, mais je suppose que c'est pareil.), et si CHAR_BIT vaut 8 (ce qui est garanti par POSIX, si je ne m'abuse), alors la valeur maximale pour un char est 127.

    Or 0xaa == 170.

    D'où débordement, sur un type signé, et donc comportement indéfini (en C toujours).
    En utilisant unsigned char à la place, il n'y a plus débordement à ce niveau, et a vaut bien 170.

    Ensuite, j'ai un doute et la flemme de resortir la norme, mais il me semble que les opérandes de << subissent la promotion entière. Donc la valeur de a est convertie en int avant qu'on calcule le a << 8. Pasunsigned int.

    Et 170 << 8, hors débordement, ça fait 170 * 2^8 = 43520 (et donc 43690 avec le + b). Si ton int est sur plus de 16 bits, ça passe. Puis tu stockes le tout dans un short. Si short fait aussi plus de 16 bits, ça passe.

    Si short et/ou int est signé et fait 16 bits, alors je rappelle que la valeur max d'un type signé sur 16 bits est 32767... i.e. il y aura débordement (et donc comportement indéfini pour ceux qui suivent).

    D'où, sauf erreur de ma part, une solution :
    unsigned char a = 0xaa;
    unsigned char b = 0xaa;
    unsigned short s1 = a << 8 + b;
    /* si jamais je me suis trompé sur la promotion entière */
    unsigned short s2 = (((unsigned int) a) << 8) + b;


    Vu tous les comportements indéfinis rencontrés en chemin, je ne prends pas la peine de chercher pourquoi tu as 0xa9aa plutôt que -1, 42 ou SIGSEV...