Использование size_t для определения точности строки в printf C - PullRequest
6 голосов
/ 10 ноября 2011

У меня есть структура для представления строк в памяти, которая выглядит следующим образом:

typedef struct {
    size_t l;
    char   *s;
} str_t;

Я считаю, что использование size_t имеет смысл для указания длины строки символа.Я также хотел бы напечатать эту строку, используя printf("%.*s\n", str.l, str.s).Однако точность * предполагает аргумент int, а не size_t.Я не смог найти что-нибудь подходящее по этому поводу.Есть ли способ правильно использовать эту структуру без приведения к int в вызове printf()?

Ответы [ 3 ]

5 голосов
/ 10 ноября 2011
printf("%.*s\n", (int)str.l, str.s)
//               ^^^^^ use a type cast

Редактировать

ОК, я не правильно прочитал вопрос. Вы не хотите использовать приведение типа, но я думаю, в этом случае: жесткий.

Либо так, либо просто используйте fwrite

fwrite(str.s, str.l, 1, stdout);
printf("\n");
3 голосов
/ 10 ноября 2011

Вы могли бы сделать макрос

#define STR2(STR) (int const){ (STR).l }, (char const*const){ (STR).s }

и затем используйте это как printf("%.*s\n", STR2(str)).

Помните, что это оценивает STR дважды, так что будьте осторожны с побочными эффектами, но вы, вероятно, уже знали об этом.

Edit:

Я использую составные инициализаторы, так что это неявные преобразования. Если что-то пойдет не так, больше шансов, что компилятор предупредит вас, чем при явном приведении.

Например, если STR имеет поле .l, являющееся указателем, и вы бы поместили приведение только к int, все компиляторы с радостью преобразуют этот указатель в int. Аналогично для поля .s это действительно должно соответствовать char* или чему-то совместимому, в противном случае вы увидите предупреждение или ошибку.

1 голос
/ 10 ноября 2011

Нет гарантии, что size_t является целым числом или что оно может быть представлено внутри целого числа. Это всего лишь часть наследства C в том, что он не определяет точный размер int, в сочетании с опасениями, что реализация size_t может потребоваться для решения проблем с большими областями памяти (в тех, которые содержат более MAX_INT-значений).

Самая распространенная ошибка, связанная с size_t, заключается в предположении, что она эквивалентна unsigned int. Такие старые ошибки были распространены, и из личного опыта это делает перенос с 32-битной на 64-битную архитектуру болезненным, так как вам нужно отменить это предположение.

В лучшем случае вы можете использовать актерский состав. Если вы действительно хотите избавиться от актеров, вы можете отказаться от использования size_t.

...