Short answer:
#define INTEGER_STRING_SIZE(t) (sizeof (t) * CHAR_BIT / 3 + 3)
unsigned long x;
char buf[INTEGER_STRING_SIZE(x)];
int len = snprintf(buf, sizeof buf, "%lu", x);
if (len < 0 || len >= sizeof buf) Handle_UnexpectedOutput();
OP's use of sizeof(unsigned long)*8
is weak. On systems where CHAR_BIT
(the # of bits per char
) is large (it must be at least 8), sizeof(unsigned long)
could be 1. 1*8
char
is certainly too small for 4294967295
(the minimum value for ULONG_MAX
).
Concerning: sprintf()/snprintf()
Given locale issues, in theory, code may print additional characters like 4,294,967,295
and so exceed the anticipated buffer. Unless very tight memory constraints occur, recommend a 2x anticipated sized buffer.
char buf[ULONG_STRING_SIZE * 2]; // 2x
int len = snprintf(buf, sizeof buf, "%lu", x);
The expected maximum string width of printing some unsigned integer is ceil(log10(unsigned_MAX)) + 1
. In the case of of unsigned long
, the value of ULONG_MAX
certainly does not exceed pow(2,sizeof (unsigned long) * CHAR_BIT) - 1
so code could use:
#define LOG10_2 0.30102999566398119521373889472449
#define ULONG_STRING_SIZE (sizeof (unsigned long) * CHAR_BIT * LOG10_2 + 2)
// For greater portability, should use integer math.
#define ULONG_STRING_SIZE (sizeof (unsigned long) * CHAR_BIT / 3 + 2)
// or more precisely
#define ULONG_STRING_SIZE (sizeof (unsigned long) * CHAR_BIT * 28/93 + 2)
The short answer used +3
in case a signed` integer was specified.