整数をテキストに変換するときは、通常、潜在的な結果を保持するために使用する大きなバッファーを作成します。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
つの思慮深いアプローチを提供します
。asprintf()
snprintf()
1 方程式を使用したコンパイル時の最大バッファ サイズ(sizeof(integer_type)*CHAR_BIT*0.302) + 3
は、壊れたり改善されたりしませんでした。の影響は<locale.h>
@paddy によって提案されたように調査され、ロケール設定は整数変換に影響しませんでし%d %x %u %i
た。型が符号付きまたは符号なしであることがわかっている場合は、式がわずかに改善される可能性があることがわかりました (以下を参照)。「より保守的」に関する@paddyの注意は良いアドバイスです。
2asprintf()
は本当に優れた汎用ソリューションですが、移植性はありません。多分ポストC11で?
3snprintf()
は標準ですが、提供されたバッファーのサイズが小さすぎる場合の既知の一貫した実装の問題があります。これは、オーバーサイズのバッファーで呼び出してから、適切なサイズのバッファーを生成することを意味します。@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
。