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
.