Comment écrire une fonction à temps constant pour copier le bit le plus significatif dans tous les bits

J’aimerais écrire une fonction, en C, qui prend le MSB de uint8_t et, si elle est définie, renvoie 0xFF et sinon 0x00 . En bref, qui retourne un entier où tous les bits ont la même valeur que le MSB.

Mais je voudrais le faire de manière totalement constante dans le temps, sans twigs, ni décalages de tableaux, mais juste des opérations mathématiques qui garantissent de toujours toucher le même nombre de bits. Et idéalement, sans aucun comportement indéfini. Comment cela peut-il être fait?

Que diriez-vous:

 #define uint8_msb_to_all_bits(x) (0xFF * ((x) >> 7)) 

ou même mieux:

 #define uint8_msb_to_all_bits(x) (-((x) >> 7)) 

La façon dont ces deux éléments fonctionnent est que, si x est un entier non signé de 8 bits, alors x >> 7 est égal à 1 si le bit de poids fort de x est défini et à 0 sinon. Il ne rest plus qu’à mapper 1 sur 0xFF, ce qui peut être fait soit par multiplication, soit, dans ce cas particulier, simplement en annulant le nombre.

(Oui, la négation d’un nombre non signé est bien définie en C ).

Qu’en est-il de

 - (x >> 7) 

?

Seul le MSB est conservé et la négation mathématique est utilisée pour le répliquer sur tous les bits.

Compte tenu de la déclaration de votre uint8_t :

 uint8_t x = // MSB is either 1 or 0 if `x` depending on the signed value of `x` 

Un sortingche qui suppose un complément à 2 pour les entiers signés:

 return (((uint16_t)(int8_t)x) >> 8) & 0xff;