web-dev-qa-db-fra.com

Pourquoi C n'a-t-il pas de littéraux binaires?

Je souhaite souvent pouvoir faire quelque chose comme ça en c:

val1 &= 0b00001111; //clear high nibble
val2 |= 0b01000000; //set bit 7
val3 &= ~0b00010000; //clear bit 5

Avoir cette syntaxe semble être un ajout incroyablement utile à C sans aucun inconvénient auquel je peux penser, et cela semble être une chose naturelle pour un langage de bas niveau où le bit-twiddling est assez courant.

Edit: je vois d'autres excellentes alternatives mais elles se désagrègent toutes quand il y a un masque plus complexe. Par exemple, si reg est un registre qui contrôle les broches d'E/S sur un microcontrôleur et que je veux mettre les broches 2, 3 et 7 à la même hauteur, je pourrais écrire reg = 0x46; Mais J'ai dû y passer 10 secondes à y penser (et je devrai probablement y passer 10 secondes à nouveau chaque fois que je lis ces codes après ne pas les avoir regardés pendant un jour ou deux) ou je pourrais écrire reg = (1 << 1) | (1 << 2) | (1 << 6); mais personnellement, je pense que c'est beaucoup moins clair que d'écrire simplement `reg = 0b01000110; ' Je peux convenir que cela n'évolue pas bien au-delà des architectures 8 bits ou peut-être 16 bits. Non pas que j'aie jamais eu besoin de faire un masque 32 bits.

29
Drew

Selon Justification de la norme internationale - Langages de programmation C §6.4.4.1 Constantes entières

Une proposition visant à ajouter des constantes binaires a été rejetée en raison d'un manque de précédent et d'une utilité insuffisante.

Ce n'est pas en C standard, mais GCC le prend en charge comme une extension, préfixée par 0b ou 0B:

 i = 0b101010;

Voir ici pour plus de détails.

37
Yu Hao

C'est ce qui a poussé hexadécimal à être ... hexadécimal. "... l'utilisation principale de la notation hexadécimale est une représentation conviviale des valeurs codées en binaire dans l'informatique et l'électronique numérique ...". Ce serait comme suit:

val1 |= 0xF;
val2 &= 0x40;
val3 |= ~0x10;

Hexadécimal:

  1. Un chiffre hexadécimal peut représenter un quartet (4 bits ou un demi octal).
  2. Deux chiffres hexadécimaux peuvent représenter un octet (8 bits).
  3. L'hex est beaucoup plus compact lors de la mise à l'échelle vers des masques plus grands.

Avec un peu de pratique, la conversion entre hexadécimal et binaire deviendra beaucoup plus naturelle. Essayez d'écrire vos conversions à la main et n'utilisez pas de convertisseur de notation bin/hex en ligne - puis dans quelques jours, cela deviendra naturel (et plus rapide en conséquence).

Mis à part: Même si les littéraux binaires ne sont pas une norme C, si vous compilez avec GCC, il est possible d'utiliser des littéraux binaires, ils doivent être préfixés avec '0b 'ou' 0B '. Voir la documentation officielle ici pour plus d'informations. Exemple:

int b1 = 0b1001; // => 9
int b2 = 0B1001; // => 9
15
Jacob Pollack

Tous vos exemples peuvent être écrits encore plus clairement:

val1 &= (1 << 4) - 1; //clear high nibble
val2 |= (1 << 6); //set bit 6
val3 &=~(1 << 3); //clear bit 3

(J'ai pris la liberté de fixer les commentaires à compter à partir de zéro, comme le voulait la nature.)

Votre compilateur pliera ces constantes, il n'y a donc aucune pénalité de performance à les écrire de cette façon. Et ceux-ci sont plus faciles à lire que les 0b... versions.

9
Nemo

Je pense que la lisibilité est une préoccupation majeure. Bien que de bas niveau, ce sont les êtres humains qui lisent et maintiennent votre code, pas la machine.

Est-il facile pour vous de comprendre que vous avez tapé par erreur 0b1000000000000000000000000000000(0x40000000), où vous voulez vraiment dire 0b10000000000000000000000000000000(0x80000000)?

7
Eric Z

"Par exemple, si reg est un registre qui contrôle les broches d'E/S sur un microcontrôleur"

Je ne peux m'empêcher de penser que c'est un mauvais exemple. Les bits des registres de contrôle ont des fonctions spécifiques (tout comme les appareils connectés à des bits individuels IO).

Il serait beaucoup plus judicieux de fournir des constantes symboliques pour les modèles de bits dans un fichier d'en-tête, plutôt que de travailler sur le binaire dans le code. La conversion du binaire en hexadécimal ou octal est triviale, se souvenant de ce qui se passe lorsque vous écrivez 01000110 dans un registre IO ne l'est pas, surtout si vous n'avez pas la fiche technique ou le schéma de circuit à portée de main.

Vous économiserez alors non seulement ces 10 secondes en essayant de travailler sur le code binaire, mais peut-être le temps un peu plus long pour essayer de comprendre ce qu'il fait!

3
Simon