Спецификатор строки ( %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 уже, так что нет оправдания, чтобы не использовать его больше.

Другие вопросы по тегам