Получить размер буфера символов для sprintf, обрабатывающего длинные строки C

#c #pointers #long-integer

#c #указатели #длинное целое число

Вопрос:

Я совсем новичок в C, и у меня возник вопрос, когда я имею дело с длинными целыми числами / символами * в C. Я хочу сохранить long в char *, но я не уверен, как мне следует управлять размером моего буфера, чтобы соответствовать любому заданному long. Это то, что я хочу:

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

Мне нужно использовать C, а не C . Есть ли какое-либо решение для этого, если я не хочу использовать магические числа?

Комментарии:

1. Количество цифр = количество бит / 3,32 1 для знака 1 для нулевого терминатора. Таким образом, для 32 бит требуется 12, для 64 требуется 22 и т.д.

Ответ №1:

если я не хочу использовать магические числа

Использование snprintf() с буфером длиной 0 вернет количество символов, необходимое для хранения результата (минус конечный 0). Затем вы можете выделить достаточно места для хранения строки по требованию:

 #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 charsn", buffer, len);
  free(buffer);
}
  

Существует также asprintf() , доступный в Linux glibc и некоторых BSD, который выделяет для вас результирующую строку с более удобным (но менее переносимым) интерфейсом, чем приведенный выше.

Выделение необходимого пространства по требованию вместо использования фиксированного размера имеет некоторые преимущества; он будет продолжать работать без дополнительной настройки, если вы измените строку формата в какой-то момент в будущем, например.

Даже если вы придерживаетесь буфера фиксированной длины, я рекомендую использовать snprintf() over sprintf() , чтобы убедиться, что вы каким-то образом не перезапишете буфер.

Ответ №2:

Вероятно, правильнее использовать snprintf для вычисления необходимого размера, но, похоже, это должно сработать:

 char buf[ sizeof(long) * CHAR_BIT ];
  

Ответ №3:

Количество битов в a long равно sizeof long * CHAR_BIT . ( CHAR_BIT определяется в <limits.h> .) Это может представлять не более знакового числа величиной 2 sizeof long * CHAR_BIT - 1 .

Такое число может содержать не более половины (log 10 2 sizeof long * CHAR_BIT - 1 ) 1 десятичных цифр. Это floor( (sizeof long * CHAR_BIT - 1) * log 10 2) 1. log 10 2 меньше .302, поэтому (sizeof long * CHAR_BIT - 1) * 302 / 1000 1 байтов достаточно для цифр.

Добавьте один для знака и один для завершающего нулевого символа, и char[(sizeof long * CHAR_BIT - 1) * 302 / 1000 3] этого достаточно для буфера.