Jak poprawić określanie rozmiaru bufora dla drukowania różnych typów liczb całkowitych?

Podczas konwersji liczby całkowitej na tekst zazwyczaj tworzęduży bufor do użyciasprintf() trzymać potencjalny wynik.

char BigBuffer[50];
sprintf(BugBuffer, "%d", SomeInt);

Chciałbym bardziej wydajne miejsce i na pewno przenośne, więc zamiast50, znalazł alternatywę:
(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

Więcpytania są:
1 Czy istnieje problem z równaniem alternatywnym?
2 Jakie lepsze rozwiązanie? - ponieważ ta alternatywa jest odrobinę marnotrawna i wygląda na zbyt skomplikowaną.

[EdytowaćOdpowiedź]

Odpowiedzi dostarczają 3 przemyślanych podejść:
1 Użyj bufora [maksymalny rozmiar dla typu] (Wybrano odpowiedź)
2 asprintf()
3 snprintf()

1 Maksymalny rozmiar czasu kompilacji za pomocą równania(sizeof(integer_type)*CHAR_BIT*0.302) + 3 nie został złamany ani ulepszony. Wpływ<locale.h> został przebadany zgodnie z sugestią @paddy i żadne ustawienia regionalne nie miały wpływu na konwersje liczb całkowitych%d %x %u %i. Stwierdzono, że można nieco poprawić równanie, jeśli wiadomo, że typ jest podpisany lub niepodpisany (poniżej). @paddy ostrożność na temat „bardziej konserwatywny” to dobra rada.

2 asprintf() jest naprawdę dobrym rozwiązaniem uniwersalnym, ale nie przenośnym. Może w post-C11?

3 snprintf(), chociaż standard, ma znane problemy z implementacją, gdy dostarczony bufor jest niewystarczający. Oznacza to wywołanie go za pomocą bufora o dużych rozmiarach, a następnie wygenerowanie buforu o odpowiednim rozmiarze. @jxh zasugerował bezpieczny globalny bufor scratch wątku, aby utworzyć odpowiedź z lokalnym buforem o odpowiednim rozmiarze. To nowatorskie podejście zasługuje na uwagę, którą mogę wykorzystać, ale pierwotne pytanie bardziej skupiało się na określeniu przeds(n)printf() nazwij konserwatywny rozmiar bufora.

signed ((sizeof(integer_type)*CHAR_BIT-1)*0.302) + 3
unsigned (sizeof(integer_type)*CHAR_BIT*0.302) + 2
*28/93 może być używany zamiast*0.302.

questionAnswers(4)

yourAnswerToTheQuestion