Определить макрос из содержимого макроса - PullRequest
7 голосов
/ 24 сентября 2011

Можно ли определить макрос из содержимого макроса?

Например:

#define SET(key,value) #define key value

SET(myKey,"value")

int main(){
   char str[] = myKey;
   printf("%s",str);
}

приведет к

int main(){
   char str[] = "value";
   printf("%s",str);
}

послепредварительно обработанный.

Зачем мне это делать? Потому что мне любопытно;)

Ответы [ 5 ]

5 голосов
/ 24 сентября 2011

Нет, невозможно определить макрос в другом макросе.

2 голосов
/ 24 сентября 2011

Препроцессор выполняет итерации только один раз перед компилятором.То, что вы предлагаете, потребует неопределенного количества итераций.

1 голос
/ 21 января 2012

Нет, вы не можете - # в списке замены макроса означает QUOTE NEXT TOKEN. Это скорее проблема орфографии, чем любая логическая головоломка:)

(Если вам требуется такое решение в вашем коде, то есть способы и приемы использования макросов, но вам нужно быть конкретным в отношении нужных вам вариантов использования - в качестве примера можно добиться, определив: #define mykey "значение")

Вот это от стандарта ANSI C99

6.10.3.2 Оператор #

Ограничения

1 Каждый # токен предварительной обработки в списке замены для функциональный макрос должен сопровождаться параметром в качестве следующего токен предварительной обработки в списке замен. Семантика 2 Если в список замены, параметру сразу предшествует # токен предварительной обработки, оба заменяются одной символьной строкой токен предварительной обработки, который содержит написание последовательность предварительной обработки токена для соответствующего аргумента. каждый появление пробела между токенами предварительной обработки аргумента становится одним пробелом в символьной строке. Пробел перед первым токеном предварительной обработки и после последнего маркер предварительной обработки, составляющий аргумент, удаляется. В противном случае оригинальное написание каждого токена предварительной обработки в аргументе сохраняется в символьной строке, за исключением специальной обработки для создания написания строковых литералов и символьных констант: \ символ вставляется перед каждым символом "и \" символа константа или строковый литерал (включая символы-разделители), за исключением того, что это определяется реализацией, является ли символ \ вставляется перед началом символа \ универсальное имя символа. Если полученная замена не является допустимой символьной строкой буквально, поведение не определено. Строка буквального символа соответствует пустому аргументу "". Порядок оценки № и ## операторы не указаны.

0 голосов
/ 13 января 2012

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

Вот некоторые фрагменты кода из некоторых моих заголовков.

// use defineStringsIn_X_File to define a NSString constant to a literal value.
// usage (direct)   : defineStringsIn_X_File(constname,value);

#define defineStringsIn_h_File(constname,value)   extern NSString * const constname; 
#define defineStringsIn_m_File(constname,value)   NSString * const constname = value; 


// use defineKeysIn_X_File when the value is the same as the key. 
// eg myKeyname has the value @"myKeyname"
// usage (direct)   : defineKeysIn_X_File(keyname);
// usage (indirect) : myKeyDefiner(defineKeysIn_X_File);
#define defineKeysIn_h_File(key)  defineStringsIn_h_File(key,key) 
#define defineKeysIn_m_File(key)  defineStringsIn_m_File(key,@#key) 



// use defineKeyValuesIn_X_File when the value is completely unrelated to the key - ie you supply a quoted value.
// eg myKeyname has the value @"keyvalue"
// usage: defineKeyValuesIn_X_File(keyname,@"keyvalue");
// usage (indirect) : myKeyDefiner(defineKeyValuesIn_X_File);
#define defineKeyValuesIn_h_File(key,value)   defineStringsIn_h_File(key,value)  
#define defineKeyValuesIn_m_File(key,value)   defineStringsIn_m_File(key,value) 



// use definePrefixedKeys_in_X_File when the last part of the keyname is the same as the value.
// eg myPrefixed_keyname has the value @"keyname"
// usage (direct)   : definePrefixedKeys_in_X_File(prefix_,keyname);
// usage (indirect) : myKeyDefiner(definePrefixedKeys_in_X_File);

#define definePrefixedKeys_in_h_File_2(prefix,key) defineKeyValuesIn_h_File(prefix##key,@#key) 
#define definePrefixedKeys_in_m_File_2(prefix,key) defineKeyValuesIn_m_File(prefix##key,@#key) 

#define definePrefixedKeys_in_h_File_3(prefix,key,NSObject) definePrefixedKeys_in_h_File_2(prefix,key)
#define definePrefixedKeys_in_m_File_3(prefix,key,NSObject) definePrefixedKeys_in_m_File_2(prefix,key)

#define definePrefixedKeys_in_h_File(...) VARARG(definePrefixedKeys_in_h_File_, __VA_ARGS__)
#define definePrefixedKeys_in_m_File(...) VARARG(definePrefixedKeys_in_m_File_, __VA_ARGS__)




// use definePrefixedKeyValues_in_X_File when the value has no relation to the keyname, but the keyname has a common prefixe
// eg myPrefixed_keyname has the value @"bollocks"
// usage: definePrefixedKeyValues_in_X_File(prefix_,keyname,@"bollocks");
// usage (indirect) : myKeyDefiner(definePrefixedKeyValues_in_X_File);
#define definePrefixedKeyValues_in_h_File(prefix,key,value) defineKeyValuesIn_h_File(prefix##key,value) 
#define definePrefixedKeyValues_in_m_File(prefix,key,value) defineKeyValuesIn_m_File(prefix##key,value) 







#define VA_NARGS_IMPL(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, N, ...) N
#define VA_NARGS(...) VA_NARGS_IMPL(X,##__VA_ARGS__, 11, 10,9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define VARARG_IMPL2(base, count, ...) base##count(__VA_ARGS__)
#define VARARG_IMPL(base, count, ...) VARARG_IMPL2(base, count, __VA_ARGS__) 
#define VARARG(base, ...) VARARG_IMPL(base, VA_NARGS(__VA_ARGS__), __VA_ARGS__)

и пример использования, который вызывает его:

#define sw_Logging_defineKeys(defineKeyValue) \
/** start of key list for sw_Logging_ **/\
/**/defineKeyValue(sw_Logging_,log)\
/**/defineKeyValue(sw_Logging_,time)\
/**/defineKeyValue(sw_Logging_,message)\
/**/defineKeyValue(sw_Logging_,object)\
/**/defineKeyValue(sw_Logging_,findCallStack)\
/**/defineKeyValue(sw_Logging_,debugging)\
/**/defineKeyValue(sw_Logging_,callStackSymbols)\
/**/defineKeyValue(sw_Logging_,callStackReturnAddresses)\
/** end of key list for sw_Logging_ **/
sw_Logging_defineKeys(definePrefixedKeys_in_h_File);

последняя часть может быть немного трудной, чтобы разобраться.макрос sw_Logging_defineKeys () определяет список, который принимает имя макроса в качестве его параметра (defineKeyValue), который затем используется для вызова макроса, который выполняет фактический процесс определения.т. е. для каждого элемента в списке переданное имя макроса используется для определения контекста («заголовок» или «реализация», например, файл «h» или «m», если вы понимаете расширение файла c);в то время как это используется для цели c, это просто старые старые макросы c, используемые для «более высокой цели», чем возможно Керниган и Ричи , когда-либо предполагаемые.:-)

0 голосов
/ 25 сентября 2011

Макросы - это простая подстановка текста.Генерация новых директив препроцессора из макроса потребует от препроцессора продолжения предварительной обработки с начала замены.Однако стандарт определил предварительную обработку для продолжения за заменой.

Это имеет смысл с точки зрения потоковой передачи, рассматривая необработанный код в качестве входного потока и обработанный (и замещенный) кодв качестве выходного потока.Подстановки макросов могут иметь произвольную длину, что означает для предварительной обработки с начала, что произвольное количество символов должно быть вставлено в начало входного потока для повторной обработки.

Когда обработка продолжается после подстановки, тогда ввод просто обрабатывается за один проход без какой-либо вставки или буферизации, потому что все напрямую идет на вывод.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...