Спецификатор строки ( %d, %f и т. д.)
#include <stdio.h>
#define Type int
int main()
{
Type x=3;
printf("%d",x);
return 0;
}
Код прост и отлично работает. Мой вопрос, если я изменюсь #define Type int
в #define Type float
поэтому я должен изменить %d
в %f
также. Есть ли способ иметь общий спецификатор, который будет работать для всех int
, float
, char
, string
итд... так что если я поменяю #define Type int
тогда мне не нужно менять спецификаторы формата в printf()
функционировать?
2 ответа
Вот что я предлагаю:
#include <stdio.h>
#define TYPE int
#define TYPE_FORMAT "%d"
int main()
{
TYPE x=3;
printf("Value of x is: " TYPE_FORMAT "\n", x);
return 0;
}
Там нет способа сделать printf()
автоопределение типов в C. В C++ вы можете использовать перегруженные <<
оператор, и это автоматически определяет типы, но C не имеет ничего подобного.
Но вы можете #define
формат и тип, и если вы поместите несколько строковых литералов рядом друг с другом, компилятор C автоматически объединит их в одну строковую константу.
PS вместо использования #define
для типа, вы, вероятно, должны использовать typedef
вот так:
typedef int TYPE;
Это означает, что в отладчике вы можете видеть, что ваша переменная x
имеет тип TYPE
в то время как с #define
вы бы увидели это как тип int
,
И в идеальном мире вы бы объявили строку формата следующим образом:
static char const * const TYPE_FORMAT = "%d";
Но мы не живем в идеальном мире. Если вы делаете вышеуказанную декларацию для TYPE_FORMAT
Компилятор, вероятно, недостаточно умен, чтобы объединить строку с другими строковыми литералами. (Я попробовал это с GCC, и, как я ожидал, я получил сообщение об ошибке.) Так что для TYPE_FORMAT
Вы обязательно должны использовать #define.
Резюме: используйте typedef
для типа, но используйте #define
для формата.
С новым стандартом C C11 вы можете использовать типовые выражения типа этого
#define MYFORMAT(X) \
_Generic(+(X) \
int: "%d", \
float: "%g", \
double: "%g", \
... whatever ... \
)
а затем использовать это как
printf("the value is " MYFORMAT(x), x);
Последняя версия компилятора clang реализует _Generic
уже, так что нет оправдания, чтобы не использовать его больше.