Я хотел бы напечатать макрокоманду (развернуть макрос) в директиве #warning.
Например, для кода:
#define AAA 17
#warning AAA = ???
Желаемый результат компиляции -
warning: AAA = 17
Что я использую для?, или, как мне увеличить код?
Я хотел бы напечатать макрокоманду (развернуть макрос) в директиве #warning.
Например, для кода:
#define AAA 17
#warning AAA = ???
Желаемый результат компиляции -
warning: AAA = 17
Что я использую для?, или, как мне увеличить код?
Вы можете использовать директиву препроцессора #pragma message
.
Пример:
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#define AAA 123
#pragma message "content of AAA: " STR(AAA)
int main() { return 0; }
Результат может выглядеть так:
$ gcc test.c
test.c:5:9: note: #pragma message: content of AAA: 123
#pragma message("content of AAA: " STR(AAA))
^
Для справки:
Я бы не рекомендовал использовать #warning, так как он не является стандартным C. Кроме того, что есть, что вы хотите предупредить против, но не сбрасывать ошибку? Предупреждения, как правило, используются компилятором, когда вы делаете что-то подозрительное, что мы совершенно опасны, но разрешено стандартом C. У вас нет такого случая в обычном приложении, вы хотите, чтобы он либо скомпилировался безупречно, либо совсем не был. Поэтому я бы использовал стандартный #error, а не нестандартный #warning.
Вы не можете ввести фактическое содержимое предпроцессорного определения. Возможно, что-то вроде этого:
#if (AAA < SOMETHING) && (AAA > SOMETHING_ELSE)
#error AAA is bad.
#endif
Я думаю, что это достаточно подробно для программиста. Однако, если вам действительно нужна дополнительная информация, и у вас есть современный компилятор C, вы можете использовать static_assert. Тогда вы можете достичь чего-то близкого к тому, что хотите:
#include <assert.h>
#define xstr(s) str(s)
#define str(s) #s
#define err_msg(x) #x " is " xstr(x)
#define AAA 17
static_assert(AAA != 17, err_msg(AAA));
этот макрос беспорядок должен печатать AAA равно 17. Объяснение того, как эти макросы работают, можно найти здесь.
Я не уверен, был ли static_assert включен в C99 или C11, это, безусловно, в C11. Возможно, вам придется использовать некоторое расширение GCC, чтобы включить его.
Если вы действительно хотите выпустить предупреждение, будет работать и следующее. Тем не менее, это зависит от включенности C99 (работает с gcc 4.8.2 или новее, не тестировалось в более ранних версиях):
#define N 77
#define __STRINGIFY(TEXT) #TEXT
#define __WARNING(TEXT) __STRINGIFY(GCC warning TEXT)
#define WARNING(VALUE) __WARNING(__STRINGIFY(N = VALUE))
#if N == 77
_Pragma (WARNING(N))
#endif
Много раз у меня есть файл Makefile, создающий локальный файл сгенерированный .h, который содержит нужные определения.
generated.h: Makefile echo >generated.h "// WARNING: generated file. Change Makefile instead" date >>generated.h '+// generated on %Y-%m-%d %H:%M:%S' echo >>generated.h "#if AAA == AAA_bad" echo >>generated.h "#warning \"AAA = $(AAA_bad)\"" echo >>generated.h "#endif"
Необходимость #include "сгенерирована .h" очевидна.
Естественно, вы можете наворотить любую сложность здесь, но если он получит больше, чем несколько строк, вы можете хотите поместить сложность в отдельный script, поскольку загроможденные Make файлы могут быть ужасными обслуживание проблема. С небольшим воображением вы можете иметь петли, генерирующие большое количество тестов с небольшого ввода.
Наличие цели сгенерированного .h зависит от Makefile имеет решающее значение для обеспечения сгенерированного .h переделано, если команды в целевом изменении. Если у вас есть отдельный сгенерированный .sh script, который тоже будет в списке зависимостей.
Отказ от ответственности: не проверены на реальность.