Препроцессор C определяет заменить спецификатор формата строки

Мне интересно, можно ли использовать определение предварительной обработки C для изменения спецификатора формата строки. Я попытался написать следующее, но, похоже, получаю ошибку компилятора. Он просто пытается заменить существующие спецификаторы формата правильными.

#include <stdio.h>

//This is the problem line....
#define %d %llu    

int main(int argc, char** argv){
    unsigned long long int myInt = 0;

    printf("myInt start value: %d", myInt++);
    printf("myInt value=%d (that got incremented)", myInt++);
    printf("myInt value: %d; wow, another post-increment", myInt++);
    printf("myInt final value %d", myInt);

    return 0;    
}

Я получаю следующую ошибку компилятора:

error: expected an identifier
  #define %d %llu
          ^

Почему этот синтаксис не приемлем? Возможно ли это сделать?

2 ответа

Решение

То, что вы хотите сделать, не возможно.

Макросы не заменяются строковыми литералами, и правила для допустимых имен идентификаторов также применяются к именам макросов.

Что вы можете сделать, это что-то вроде этого:

#if xyz
  #define FMT   "%d"
#else
  #define FMT   "%lli"
#endif

....

printf("myInt start value: " FMT "\n", myInt++);

Кстати: обычно вам это не нужно. Для родных типов int, long и т.д. спецификаторы формата должны использоваться как обычно.

Для типов с фиксированным размером (например, int64_t и т.д.) в inttypes.h уже определены макросы

Возможно ли это сделать? Нет, это невозможно, как вы делаете. В заявлении

#define %d %lli 

имя макроса должно быть допустимым идентификатором.

От C99 стандарт

раздел 6.10.1

# define identifier replacement-list new-line

и из 7.1.13

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

Сделайте имя макроса допустимым идентификатором. например, определить макрос как

#define INT_FMT "%d"

а потом

 int myInt = 10;
 printf("myInt start value is : "  INT_FMT  "\n", myInt);
Другие вопросы по тегам