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

StackOverflow https://stackoverflow.com/questions/1661369

  •  12-09-2019
  •  | 
  •  

Вопрос

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

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

#include <stdio.h>

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

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

Это было полезно?

Решение

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

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

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

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

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

Другие советы

Будь осторожен!

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

int a = 005;

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

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

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

192.168.010.073

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

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

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

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

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

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

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

Тебе стоит попробовать:

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

0 означает «дополнение нулями», 3 — желаемая длина вывода.

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

Число с ведущим 0 обозначало, что число является восьмеричный число.Это называется Целочисленные литералы.Вы также можете использовать 0b для обозначения двоичное число, для шестнадцатеричное число это 0x или 0X.Вам не нужно ничего писать для десятичная дробь.См. код ниже.

#include<stdio.h>

int main()
{
    int binary = 0b10;
    int octal=010;
    int decimal = 10;
    int hexa = 0x10;
    printf("%d %d %d %d\n", octal, decimal, hexa, binary);
}

Для получения дополнительной информации посетите Учебная точка.

Целые числа не имеют «ведущих нулей», 5 — это 5, вы можете записать его строковое представление с ведущим 0, если хотите, для этого у вас есть модификаторы printf.

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

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

Обычно «%<x>d» печатает целое число шириной x символов и дополняет его начальными пробелами.«%0<x>d» будет делать то же самое, но будет дополняться ведущими нулями.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top