Как C обрабатывает целочисленные литералы с ведущими нулями и как насчет atoi?

когда вы создаете целое число с ведущими нулями, как с этим справлялся? Он отличается для разных версий C?

в моем случае они просто кажутся отброшенными (но, может быть, это то, что делает printf?):

#include <stdio.h>

int main() {
    int a = 005;
    printf("%in", a);
    return 0;
}

Я знаю, что могу использовать printf для заполнения с 0s, но мне просто интересно, как это работает.

7 ответов


ведущие нули указывают, что число выражается в восьмеричной, или база 8; таким образом, 010 = 8. Добавление дополнительных ведущих нулей не имеет никакого эффекта; как и следовало ожидать в математике, x + 0*8^n = x; нет никакого изменения значения, делая его представление более длинным.

одном месте вы часто видите это в режимы файл Unix; 0755 на самом деле означает 7*8^2+5*8+5 = 493; или с umasks, таких как 0022 = 2*8+2 = 10.

atoi(nptr) определяется как эквивалент strtol(nptr, (char **) NULL, 10), за исключением того, что он не обнаруживает ошибок - как таковой, atoi() всегда использует decimal (и, таким образом, игнорирует ведущие нули). strtol(nptr, anything, 0) делает следующее:

строка может начинаться с произвольного количество пробелов (как определено by isspace(3)), а затем один необязательно '+' или '-' знак. Если база нуль или 16, строка может тогда включить "0x" префикс и номер будет прочитано в базе 16; в противном случае a ноль базу берется 10 (дес) если следующий символ '0', в этом случае принимается 8 (восьмеричной).

поэтому он использует те же правила, что компилятор C.


будьте осторожны!

в данном заявлении 005 является восьмеричной константой.

int a = 005;

в этом случае это не имеет значения, потому что одноразрядная восьмеричная константа имеет то же значение, что и эквивалентная десятичная константа, но в C: 015 != 15

если целочисленный литерал выражен в восьмеричном, десятичном или шестнадцатеричном формате, после его анализа компилятором он просто рассматривается как значение. Как целое число выводится через printf зависит только от его типа, его значение и спецификаторы формата (и активная локаль).


тот факт, что начальный ноль указывает на восьмеричное число, часто забывается. Я видел, что это вызывает путаницу несколько раз, например, когда кто-то пытался ввести IP-адрес, используя хороший, обычный формат для октетов:

192.168.010.073

и парсер интерпретировал последние 2 октета как восьмеричные числа.

единственное, что хуже, чем неудачное использование ведущих нулей C, чтобы сделать восьмеричное число, - это обработка ведущих нулей Javascript иногда сделайте восьмеричное число (число восьмеричное, если остальные цифры в порядке-меньше 8-десятичного в противном случае). В JavaScript (017 == 15) но (018 == 18).

Я бы предпочел, чтобы была ошибка; на самом деле я бы предпочел полностью отказаться от поддержки восьмеричных букв. По крайней мере, используйте более в вашем лице префикс, например,

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

но я на 35 лет опоздал с моим предложением.


число с ведущим нулем означает восьмеричное кодирование во всех версиях C. So 011 == 9 == 0x9.

Восьмеричный-это система нумерации, основанная на 8 (вместо 10 для десятичного или 16 для шестнадцатеричного). Так что 011 == 1*8 + 1, 013 == 1*8 + 3, etc.


вы должны попробовать:

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

0 означает "колодка с нулями", 3-требуемая длина вывода.

Edit: Извините, я слишком быстро прочитал Ваш вопрос - теперь я вижу, что вы спросили о чем-то совершенно другом. Однако я оставлю это как есть, как это может быть полезно для кого-то другого.


целые числа не имеют "ведущих нулей" a 5-это 5, Вы можете написать его строковое представление с ведущим 0, если хотите, для этого у вас есть модификаторы printf.


в вашем конкретном случае нули удаляются printf. Все ведущие нули удаляются компилятором, за исключением начального нуля, который заставляет компилятор рассматривать число как восьмеричное. Для 005 и восьмеричное, и десятичное представления одинаковы и не должны беспокоить вас, но все же, это напрашивается на неприятности, если вы специально не имели в виду восьмеричное представление.

ведущие нули имеют отношение исключительно к строковому представлению целое число. Для печати с ведущими нулями используйте "%03d". Это обеспечит длину поля 3.

В общем случае "%d " будет печатать целочисленные символы x в ширину и заполнять ведущие пробелы. "%0d " будет делать то же самое, но будет заполняться ведущими нулями.