Препроцессор C определяет заменить спецификатор формата строки - PullRequest
0 голосов
/ 29 мая 2018

Мне интересно, возможно ли использовать определение предварительной обработки 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 ]

0 голосов
/ 29 мая 2018

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

#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);
0 голосов
/ 29 мая 2018

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

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

То, что вы могли бы сделать, это нечтокак это:

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

....

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

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

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

...