Depuis C++ 14, grâce à n3781 (qui en lui-même ne répond pas à cette question), nous pouvons écrire du code comme ceci:
const int x = 1'234; // one thousand two hundred and thirty four
L'objectif est d'améliorer le code comme ceci:
const int y = 100000000;
et le rendre plus lisible.
Le trait de soulignement (_
) était déjà pris en C++ 11 par des littéraux définis par l'utilisateur, et la virgule (,
) a des problèmes de localisation - de nombreux pays européens déconcertants† utilisez-le comme séparateur décimal - et entre en conflit avec l'opérateur de virgule, bien que je me demande quel code du monde réel aurait pu être brisé en permettant par exemple 1,234,567
.
Quoi qu'il en soit, une meilleure solution semble être le caractère spatial:
const int z = 1 000 000;
Ces jetons littéraux numériques adjacents pourraient être concaténés par le préprocesseur tout comme les littéraux de chaîne:
const char x[5] = "a" "bc" "d";
Au lieu de cela, nous obtenons l'apostrophe ('
), non utilisé par aucun système d'écriture que je connaisse comme séparateur de chiffres.
Y a-t-il une raison pour laquelle l'apostrophe a été choisie au lieu d'un simple espace?
† C'est déroutant parce que toutes ces langues, dans le texte, maintiennent la notion d'une virgule "séparant" une phrase par ailleurs atomique, avec une période fonctionnant pour "terminer" la phrase - pour moi, au moins, c'est assez analogue à une virgule "briser" la partie intégrante d'un nombre et une période "se terminant", il est prêt pour l'entrée fractionnaire.
Il y a un article précédent, n3499 , qui nous dit que bien que Bjarne lui-même ait suggéré des espaces comme séparateurs:
Bien que cette approche soit cohérente avec un style typographique commun, elle souffre de certains problèmes de compatibilité.
- Il ne correspond pas à la syntaxe d'un nombre pp , et nécessiterait au minimum l'extension de cette syntaxe.
- Plus important encore, il y aurait une certaine ambiguïté syntaxique lorsqu'un chiffre hexadécimal dans la plage [a-f] suit un espace. Le préprocesseur ne saurait pas s'il faut effectuer une substitution de symboles à partir de l'espace.
- Cela rendrait probablement les outils d'édition qui saisissent les "mots" moins fiables.
Je suppose que l'exemple suivant est le principal problème noté:
const int x = 0x123 a;
même si, à mon avis, cette justification est assez faible. Je ne peux toujours pas penser à un exemple du monde réel pour le briser.
La logique des "outils d'édition" est encore pire, puisque 1'234
rompt fondamentalement tous les surligneurs de syntaxe connus de l'humanité (par exemple celui utilisé par Markdown dans la question ci-dessus!) et rend les versions mises à jour desdits surligneurs beaucoup plus difficiles à implémenter.
Pourtant, pour le meilleur ou pour le pire, c'est la justification qui a conduit à l'adoption d'apostrophes à la place.
La raison évidente de ne pas utiliser d'espace blanc est qu'une nouvelle ligne est également un espace blanc et que C++ traite tous les espaces blancs de manière identique. Et en revanche, je ne connais aucune langue qui accepte un espace blanc arbitraire comme séparateur.
Vraisemblablement, Unicode 0xA0 (espace insécable) pourrait être utilisé - c'est la solution la plus utilisée lors de la composition. Je vois cependant deux problèmes avec cela: premièrement, ce n'est pas dans le jeu de caractères de base, et deuxièmement, ce n'est pas distinctif visuellement; vous ne pouvez pas voir que ce n'est pas un espace en regardant simplement le texte dans un éditeur normal.
Au-delà de cela, il n'y a pas beaucoup de choix. Vous ne pouvez pas utiliser la virgule, car il s'agit déjà d'un jeton légal (et quelque chose comme 1,234
est actuellement C++ légal, avec la signification 234). Et dans un contexte où cela pourrait se produire dans le code juridique, par exemple a[1,234]
. Bien que je ne puisse pas vraiment imaginer un vrai code utilisant réellement cela, il existe une règle de base selon laquelle aucun programme juridique, quelle que soit son absurdité, ne devrait changer la sémantique en silence.
Des considérations similaires signifient que _
ne peut pas être utilisé non plus; s'il y a un #define _234 * 2
, puis a[1_234]
changerait silencieusement la signification du code.
Je ne peux pas dire que je suis particulièrement satisfait du choix de '
, mais il a l'avantage d'être utilisé en Europe continentale, du moins dans certains types de textes. (Je semble me souvenir de l'avoir vu en allemand, par exemple, bien que dans un texte courant typique, l'allemand, comme la plupart des autres langues, utilisera un point ou un espace insécable. Mais peut-être que c'était le suisse allemand.) Le problème avec '
analyse; la séquence '1'
est déjà légal, tout comme '123'
. Donc quelque chose comme 1'234
pourrait être un 1
, suivi du début d'une constante de caractère; Je ne sais pas jusqu'où vous devez anticiper pour prendre la décision. Il n'y a pas de séquence de C++ juridique dans laquelle une constante intégrale peut être suivie d'une constante de caractère, donc il n'y a pas de problème avec la rupture du code légal, mais cela signifie que le balayage lexical devient soudainement très dépendant du contexte.
(En ce qui concerne votre commentaire: il n'y a pas de logique dans le choix d'un séparateur décimal ou de milliers. Un séparateur décimal, par exemple, n'est certainement pas un point final. Ce ne sont que des conventions arbitraires.)
De wiki , nous avons un bel exemple:
auto floating_point_literal = 0.000'015'3;
Ici, nous avons le .
et puis si un autre opérateur devait être rencontré, mes yeux attendraient quelque chose de visible, comme une virgule ou quelque chose, pas un espace.
Une apostrophe fait donc beaucoup mieux ici qu'un espace blanc.
Avec des espaces blancs, ce serait
auto floating_point_literal = 0.000 015 3;
qui ne se sent pas aussi bien que le cas avec les apostrophes.
Dans le même esprit de réponse d'Albert Renshaw , je pense que l'apostrophe est plus claire que l'espace proposé par les courses de légèreté en orbite.
type a = 1'000'000'000'000'000'544'445'555;
type a = 1 000 000 000 000 000 544 445 555;
L'espace est utilisé pour beaucoup de choses, comme la concaténation de chaînes que l'OP mentionne, contrairement à l'apostrophe, qui dans ce cas le rend clair pour quelqu'un qui est utilisé pour séparer les chiffres.
Lorsque les lignes de code deviennent nombreuses, je pense que cela améliorera la lisibilité, mais je doute que c'est la raison pour laquelle elles le choisissent.
À propos des espaces, cela pourrait valoir la peine de jeter un œil à ce C question , qui dit:
La langue ne permet pas int i = 10 000;
(un littéral entier est un jeton, l'espace blanc intermédiaire le divise en deux jetons) mais il y a généralement peu ou pas de dépenses encourues en exprimant l'initialiseur comme une expression qui est un calcul de littéraux:
int i = 10 * 1000; /* ten thousand */
Il est vrai que je ne vois aucun sens pratique à:
if (a == 1 1 1 1 1) ...
donc les chiffres peuvent être fusionnés sans réelle ambiguïté mais qu'en est-il d'un nombre hexadécimal?
0 x 1 a B 2 3
Il n'y a aucun moyen de lever l'ambiguïté d'une faute de frappe (normalement nous devrions voir une erreur)
Je suppose que c'est parce que, lors de l'écriture de code, si vous atteignez la fin d'une "ligne" (la largeur de votre écran), un saut de ligne automatique (ou "retour à la ligne") se produit. Cela provoquerait que votre int soit divisé en deux, une moitié serait sur la première ligne, la seconde moitié sur la seconde ... de cette façon, tout reste ensemble en cas de Word-wrap
.
float floating_point_literal = 0.0000153; /* C, C++*/
auto floating_point_literal = 0.0000153; // C++11
auto floating_point_literal = 0.000'015'3; // C++14
Commenter ne fait pas de mal:
/* 0. 0000 1530 */
float floating_point_literal = 0.00001530;
Les chaînes binaires peuvent être difficiles à analyser:
long bytecode = 0b1111011010011001; /* gcc , clang */
long bytecode = 0b1111'0110'1001'1001; //C++14
// 0b 1111 0110 1001 1001 would be better, really.
// It is how humans think.
Une macro à considérer:
#define B(W,X,Y,Z) (0b##W##X##Y##Z)
#define HEX(W,X,Y,Z) (0x##W##X##Y##Z)
#define OCT(O) (0##O)
long z = B(1001, 1001, 1020, 1032 );
// result : long z = (0b1001100110201032);
long h = OCT( 35);
// result : long h = (035); // 35_oct => 29_dec
long h = HEX( FF, A6, 3B, D0 );
// result : long h = (0xFFA6BD0);