Comment C gère-t-il les littéraux entiers avec des zéros non significatifs et quid de atoi?

Lorsque vous créez un entier avec des zéros non significatifs, comment c le gère-t-il? Est-ce différent pour différentes versions de C?

Dans mon cas, ils semblent juste être abandonnés (mais peut-être que c’est ce que printf fait?):

#include  int main() { int a = 005; printf("%i\n", a); return 0; } 

Je sais que je peux utiliser printf pour traiter avec des 0, mais je me demande simplement comment cela fonctionne.

Les zéros à gauche indiquent que le nombre est exprimé en octal ou en base 8; ainsi, 010 = 8. L’ajout de zéros non significatifs n’a aucun effet. exactement comme on peut s’y attendre en mathématiques, x + 0 * 8 ^ n = x; il n’y a aucun changement à la valeur en allongeant sa représentation.

Vous remarquez souvent qu’il s’agit de modes de fichiers UNIX; 0755 signifie en réalité 7 * 8 ^ 2 + 5 * 8 + 5 = 493; ou avec des masques tels que 0022 = 2 * 8 + 2 = 10.

atoi(nptr) est défini comme équivalent à strtol(nptr, (char **) NULL, 10) , à ceci près qu’il ne détecte pas les erreurs – en tant que tel, atoi() utilise toujours décimal (et ignore donc les zéros non significatifs). strtol(nptr, anything, 0) fait ce qui suit:

La chaîne peut commencer par une quantité arbitraire d’espaces (déterminée par isspace(3) ) suivie d’un seul signe facultatif '+' ou '-' . Si la base est zéro ou 16, la chaîne peut alors inclure un préfixe "0x" et le nombre sera lu en base 16; sinon, une base zéro est prise comme 10 (décimal) à moins que le caractère suivant soit '0' , auquel cas il est pris comme 8 (octal).

Donc, il utilise les mêmes règles que le compilateur C.

Faites attention!

Dans cette déclaration, 005 est une constante octale.

 int a = 005; 

Dans ce cas, cela n’a pas d’importance, car une constante octale à un chiffre a la même valeur que la constante décimale équivalente, mais en C: 015 != 15

Qu’un littéral entier soit exprimé en octal, décimal ou hexadécimal, une fois analysé par le compilateur, il est simplement traité comme une valeur. La manière dont un entier est généré via printf dépend uniquement de son type, de sa valeur et des spécificateurs de format (et des parameters régionaux actifs).

Le fait qu’un zéro au début indique qu’un nombre est octal est quelque chose qui est souvent oublié. Je l’ai vu causer de la confusion à plusieurs resockets, par exemple lorsque quelqu’un essayait de saisir une adresse IP en utilisant un format sympa et standard pour les octets:

 192.168.010.073 

et l’parsingur a interprété les 2 derniers octets comme des nombres octaux.

La seule chose pire que l’utilisation malheureuse des zéros non significatifs par C pour rendre un nombre octal est la gestion par Javascript des zéros non significatifs pour rendre parfois un nombre octal (le nombre est octal si le rest des chiffres est correct – moins de 8 – décimal sinon). En Javascript, (017 == 15) mais (018 == 18) .

Je préférerais qu’il y ait une erreur. en fait, je préférerais abandonner complètement le support octal littéral. Utilisez au moins un préfixe plus en face, comme peut-être

 0t10 (ocTal 8) 0k17 (oKtal 15) 

Mais je suis environ 35 ans trop tard avec ma proposition.

Un nombre avec un zéro au début signifie un codage octal dans toutes les versions de C. Donc 011 == 9 == 0x9 .

Octal est un système de numérotation basé sur 8 (au lieu de 10 pour le nombre décimal ou de 16 pour le format hexadécimal). Donc 011 == 1*8 + 1, 013 == 1*8 + 3 , etc.

Tu devrais essayer:

 int a = 5; printf("%03i\n", a); 

0 signifie “pavé avec zéros”, 3 est la longueur de sortie souhaitée.

Edit: Désolé, j’ai lu votre question trop rapidement – maintenant je vois que vous avez demandé quelque chose de complètement différent. Cependant, je vais laisser cela tel quel, car cela pourrait être utile à quelqu’un d’autre.

Les nombres entiers n’ont pas de “zéros au début” un 5 est un 5, vous pouvez écrire sa représentation sous forme de chaîne avec 0 au début si vous voulez, pour cela vous avez les modificateurs printf.

Dans votre cas particulier, les zéros sont supprimés par printf. Le compilateur supprime tous les zéros non significatifs, à l’exception du zéro initial qui oblige votre compilateur à traiter l’entier comme une valeur octale. Pour 005, les représentations octale et décimale sont identiques et ne doivent pas vous déranger, mais cela pose des problèmes, à moins que vous ne pensiez spécifiquement à la représentation octale.

Les zéros au début concernent uniquement la représentation sous forme de chaîne de l’entier. Pour imprimer avec des zéros, utilisez “% 03d”. Cela assurera une longueur de champ de 3.

En général, “% d” imprimera un nombre entier de x caractères et sera complété par des espaces. “% 0 d” fera la même chose mais remplira avec des zéros au début.