Почему 0 (ноль) печатается без начального "0x" в формате C printf "% # x"? - PullRequest
28 голосов
/ 15 декабря 2011

Справочная информация: у меня есть ряд скриптов, которые анализируют файлы журналов в поисках шестнадцатеричных чисел, находя ведущий «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-преобразований) к нему».

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

1 Ответ

24 голосов
/ 15 декабря 2011

Стандарт, кажется, написан так:

  • %#x и %#o пытаются гарантировать, что выходной сигнал может быть правильно проанализирован с использованием strtol с base = 0.

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

  • Если вы хотите добавить 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, чтобы сделать то, что вы хотите.

...