Препроцессор 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);