0

I am quite new to C and occurred a question, when dealing with long ints/char* in C. I want to store a long in a char*, but I am not sure, how I should manage the size of my buffer to fit any long given. Thats what I want:

char buffer[LONG_SIZE]; // what should LONG_SIZE be to fit any long, not depending on the OS?
sprintf(buffer, "%ld", some_long);

I need to use C not C++. Is there any solution to this, if I don't want to use magic-numbers?

  • Number of digits = number of bits / 3.32 + 1 for sign +1 for null terminator. So 32 bits needs 12, 64 needs 22, etc. – stark Oct 29 '20 at 16:49

3 Answers3

3

if I don't want to use magic-numbers

Using snprintf() with a 0-length buffer will return the number of chars needed to hold the result (Minus the trailing 0). You can then allocate enough space to hold the string on demand:

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

int main(void) {
  long some_long = LONG_MAX - 5;
  // Real code should include error checking and handling.
  int len = snprintf(NULL, 0, "%ld", some_long);
  char *buffer = malloc(len + 1);
  snprintf(buffer, len + 1, "%ld", some_long);
  printf("%s takes %d chars\n", buffer, len);
  free(buffer);
}

There's also asprintf(), available in Linux glibc and some BSDs, that allocates the result string for you, with a more convenient (But less portable) interface than the above.

Allocating the needed space on demand instead of using a fixed size has some benefits; it'll continue to work without further adjustment if you change the format string at some point in the future, for example.

Even if you stick with a fixed length buffer, I recommend using snprintf() over sprintf() to ensure you won't somehow overwrite the buffer.

Shawn
  • 47,241
  • 3
  • 26
  • 60
1

It is probably more correct to use snprintf to compute the necessary size, but it seems like this should work:

char buf[ sizeof(long) * CHAR_BIT ];
William Pursell
  • 204,365
  • 48
  • 270
  • 300
1

The number of bits in a long is sizeof long * CHAR_BIT. (CHAR_BIT is defined in <limits.h>.) This can represent at most a signed number of magnitude 2sizeof long * CHAR_BIT - 1.

Such a number can have at most floor(log102sizeof long * CHAR_BIT - 1)+1 decimal digits. This is floor((sizeof long * CHAR_BIT - 1) * log102) + 1. log102 is less than .302, so (sizeof long * CHAR_BIT - 1) * 302 / 1000 + 1 bytes is enough for the digits.

Add one for a sign and one for a terminating null character, and char[(sizeof long * CHAR_BIT - 1) * 302 / 1000 + 3] suffices for the buffer.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312