64566 # Buffer size for converting unsigned long to string

In reference to question and the answer here: Can I use this method so that the solution will be platform independent.

```char *buff = (char*) malloc(sizeof(unsigned long)*8); sprintf(buff, "%lu", unsigned_long_variable); ```

Here I am getting the value of buffer length as it will similar to unsigned long variable. Is this approach correct?

You want to know how many characters are needed to represent the largest possible `unsigned long`. Correct?

To that end, you are trying to calculate the largest possible `unsigned long`:

```sizeof(unsigned long)*8 ```

That is faulty in several ways. For one, `sizeof` returns multiples of `char`, which need not be 8 bit. You should multiply with `CHAR_BIT` (from `<limits.h>`) instead. But even that is not necessary, because that very same header already does provide the largest possible value -- `UCHAR_MAX`.

Then you're making a mistake: Your calculation gives the size of the integer representation of `unsigned long` in bits. What you want is the size of the string representation in characters. This can be achieved with the `log10()` function (from `<math.h>`):

```log10( UCHAR_MAX ) ```

This will give you a `double` value that indicates the number of (decimal) digits in `UCHAR_MAX`. It will be a fraction, which you need to round up (1) (`ceil()` does this for you).

Thus:

```#include <math.h> #include <stdlib.h> #include <limits.h> int main() { char * buff = malloc( ceil( log10( UCHAR_MAX ) ) + 1 ); //... } ```

All in all, this is quite dodgy (I made two mistakes while writing this out, shame on me -- if you make mistakes when using this, shame on you). And it requires the use of the math library for something that `snprintf( NULL, ... )` can do for you more easily, as indicated by the Q&A you linked to.

<hr>

(1): `log10( 9999 )` gives `3.9999565...` for the four-digit number.

Don't even try to calculate the buffer size.

Start with `snprintf`, which will tell you safely how many characters are needed. Then you know how many bytes to allocate to print safely.

Since this is a few lines of code that you don't want to repeat again and again, write a function `malloc_printf` that does exactly what you want: In that function, call `snprintf` with a NULL destination, then `malloc` the buffer, `sprintf` into the `malloc` buffer, and return it. To make it faster and to often avoid two `snprintf` and `sprintf` calls, write into a buffer of 256 chars first which is often enough.

So your final code would be

```char* buff = malloc_printf ("%lu", unsigned_long_variable); ```

Also does quick, safe and easy string concatenation using the format `%s%s`, for example.

If someone constructs a C compiler that uses for example 2000 bits per char the output can overflow the buffer.

Instead of `8` you should use `CHAR_BIT` from limits.h.

Also, note that you need (slighly less than) 1 char per 3 bits and you need 1 byte for the string terminator.

So, something like this:

```#include <limit.h> char *buff = malloc(1 + (sizeof(unsigned long) * CHAR_BIT + 2) / 3); sprintf(buff, "%lu", unsigned_long_variable); ```

No, this is not the right way to calculate the buffer size.

E.g. for 4 byte unsigned longs you have values up to 2^32-1 which means 10 decimal digits. So your buffer needs 11 chars.

You are allocating 4 * 8 = 32.

The correct formula is

```ceil(log10(2^(sizeof(unsigned long) * CHAR_BIT) - 1)) + 1 ```

(`log10` denotes the decimal logarithm here)

A good (safe) estimation is:

```(sizeof(unsigned long) * CHAR_BIT + 2) / 3 + 1 ```

because log10(2) is less than 0.33.

```#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(); ``` <hr>

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.