Как улучшить определение размера буфера для печати различных целочисленных типов?
При преобразовании целого числа в текст, как правило, я создаюбольшой буфер для использования сsprintf()
провести любой потенциальный результат.
char BigBuffer[50];
sprintf(BugBuffer, "%d", SomeInt);
Я хотел бы более экономичный и, конечно, портативный, поэтому вместо50
, нашел альтернативу:(sizeof(integer_type)*CHAR_BIT*0.302) + 3
// 0.0302 about log10(2)
#define USHORT_DECIMAL_BUFN ((size_t) (sizeof(unsigned short)*CHAR_BIT*0.302) + 3)
#define INT_DECIMAL_BUFN ((size_t) (sizeof(int) *CHAR_BIT*0.302) + 3)
#define INTMAX_DECIMAL_BUFN ((size_t) (sizeof(intmax_t) *CHAR_BIT*0.302) + 3)
int main() {
char usbuffer[USHORT_DECIMAL_BUFN];
sprintf(usbuffer, "%hu", USHRT_MAX);
printf("Size:%zu Len:%zu %s\n", sizeof(usbuffer), strlen(usbuffer), usbuffer);
char ibuffer[INT_DECIMAL_BUFN];
sprintf(ibuffer, "%d", INT_MIN);
printf("Size:%zu Len:%zu %s\n", sizeof(ibuffer), strlen(ibuffer), ibuffer);
char imbuffer[INTMAX_DECIMAL_BUFN];
sprintf(imbuffer, "%" PRIdMAX, INTMAX_MIN);
printf("Size:%zu Len:%zu %s\n", sizeof(imbuffer), strlen(imbuffer), imbuffer);
return 0;
}
Size:7 Len:5 65535
Size:12 Len:11 -2147483648
Size:22 Len:20 -9223372036854775808
Так чтовопросов находятся:
1 Есть ли проблема с альтернативным уравнением?
2 Какое лучшее решение? - поскольку эта альтернатива немного расточительна и выглядит слишком сложной.
[РедактироватьОтвет]
Ответы обеспечивают 3 продуманных подхода:
1 Используйте буфер [максимальный размер для типа] (Ответ выбран)
2 asprintf()
3 snprintf()
1 Максимальный размер буфера времени компиляции с использованием уравнения(sizeof(integer_type)*CHAR_BIT*0.302) + 3
не был сломан или улучшен. Влияние<locale.h>
был исследован в соответствии с предложением @paddy, и никакие настройки локали не влияли на целочисленные преобразования%d %x %u %i
, Было обнаружено, что в уравнение можно внести небольшие улучшения, если известно, что тип подписан или не подписан (ниже). Предупреждение @paddy о «более консервативном» - это хороший совет.
2 asprintf()
действительно хорошее универсальное решение, но не портативное. Может быть, в пост-С11?
3 snprintf()
хотя и является стандартным, имеет известные проблемы реализации, когда поставляемый буфер слишком мал. Это подразумевает вызов его с буфером большего размера, а затем генерирование буфера правильного размера. @jxh предложил потокобезопасный глобальный буфер с нуля, чтобы сформировать ответ с локальным буфером правильного размера. Этот новый подход заслуживает рассмотрения, которое я могу использовать, но первоначальный вопрос был сосредоточен на определении доs(n)printf()
назвать консервативный размер буфера.
signed ((sizeof(integer_type)*CHAR_BIT-1)*0.302) + 3
unsigned (sizeof(integer_type)*CHAR_BIT*0.302) + 2
*28/93
может быть использован вместо*0.302
.