Подтвердить что ты не робот

Почему 0 (ноль) печатается без ведущего "0x" с форматом C printf "% # x"?

Фон: у меня есть несколько скриптов, которые анализируют файлы журналов, которые ищут шестнадцатеричные числа, находя ведущий "0x". Наша встроенная библиотека C изменилась на новый printf. Новый printf является более стандартным, чем наши предыдущие, и мои скрипты сломались.

В поле Linux:

#include <stdio.h>
int main( void )
{
    printf( "%#010x\n", 0 );
    printf( "%#010x\n", 1 );
    return 0;
}

Выход (с использованием glibc):

0000000000
0x00000001

Вывод на нашем фирменном ПО:

0x00000000
0x00000001

Из printf (3), на символ символа '#': "Для преобразований x и X у ненулевого результата есть строка" 0x "(или" 0X "для конверсий X), добавленная к ней".

Мне любопытно, почему. Не копаясь в документах стандартов С или покупая обед для членов комитета по стандартам, почему бы не привести 0x к аргументу с нулевым значением?

4b9b3361

Ответ 1

Стандарт, похоже, написан таким образом:

  • %#x и %#o постарайтесь гарантировать правильную обработку вывода с помощью strtol с помощью base = 0.

  • В этих случаях флаг # добавляет как можно больше лишних символов. Например, 0 печатается как 0, потому что нет необходимости добавлять дополнительные 0x. Это имеет большой смысл, если вы не указали минимальную ширину поля и 0-дополнение.

  • Если вы хотите добавить 0x всегда, вы можете просто написать что-то вроде 0x%x. Следовательно, %#x может показаться полезным только в тех особых случаях, когда вам действительно нужна специальная обработка 0. Но предварительный запрос 0x не работает с спецификаторами ширины поля по умолчанию, например) 0x%12x право оправдано пробелами между 0x и шестнадцатеричными цифрами, что вряд ли будет тем, что нужно в этом случае. Для этого случая потребуется дополнительный подготовительный проход с помощью sprintf, поэтому шестнадцатеричная строка, такая как "0x2ac2", может быть свободным пробелом, оправданным с чем-то вроде printf( "%12s", hexstr); К счастью, оправдывая 0, а не пробелы, используя что-то вроде printf( "0x%012x", hexstr);, работает как ожидая получения действительных шестнадцатеричных цифр для синтаксического анализатора.

Теперь путь %#x указан для работы, который имеет большой смысл в изоляции. И, как указано, что-то вроде %010x задается для работы, имеет большой смысл в изоляции. Вы комбинируете эти два модификатора, и конечный результат, возможно, странный. Для другого приложения, такого как автоматическое генерирование аккуратного кода C для инициализации таблиц, наличие 0,, а не 0x0 не является проблемой.

Но нет необходимости комбинировать %#x и %010x. Вы можете просто написать 0x%08x, чтобы сделать то, что вы хотите.