Используя только те средства, которые определены в Стандарте C (C89, C99 или C11), единственный механизм «отключения» - это #undef
.
Проблема в том, что нет механизма повторного включения.
Как уже отмечали другие, если файл заголовка, содержащий определения макросов, структурирован таким образом, что он не содержит никаких объявлений typedef или enum (их нельзя повторять; объявления функций и переменных могут повторяться), тогда вы могли бы #undef
макрос, делайте то, что вам нужно, без действующего макроса, а затем повторно включите заголовок, возможно, после отмены определения его защиты от повторного включения.
Если макросы не определены в заголовке, конечно, вы застряли, пока не выполните рефакторинг кода, чтобы они были в заголовке.
Доступен еще один прием - если макросы являются функциональными макросами, а не объектными макросами.
#define nonsense(a, b) b /\= a
int (nonsense)(int a, int b)
{
return (a > b) ? a : b;
}
Функция nonsense()
определена нормально, несмотря на макрос непосредственно перед ней. Это связано с тем, что за вызовом макроса (для функционально-подобного макроса) должна немедленно следовать открывающая скобка (дать или взять пробел, возможно, включая комментарии). В строке определения функции токен после «ерунды» является закрывающей скобкой, поэтому он не является вызовом макроса nonsense
.
Если бы макрос был объектно-подобным макросом без аргументов, трюк не сработал бы:
#define nonsense min
int (nonsense)(int a, int b)
{
// Think about it - what is the function really called?
return (a > b) ? a : b;
}
Этот код определяет фиктивную функцию, которая называется min
и является бессмысленной. И от макроса нет защиты.
Это одна из причин, по которой стандарт тщательно определяет, какие пространства имен зарезервированы для «Реализации». Реализация позволяет определять макросы для любых целей, которые она желает или нуждается, любого типа (функционального или объектного), которые она желает или нуждается, при условии, что эти имена зарезервированы для реализации. Если вы, как потребитель услуг Реализации, попытаетесь использовать или определить имя, зарезервированное для реализации, вы должны знать, что ваш код, вероятно, рано или поздно сломается, и что это будет ваша вина, а не ошибка Осуществление.