Например, возможно ли следующее:
#define definer(x) #define #x?
Например, возможно ли следующее:
#define definer(x) #define #x?
Хотя ваш синтаксис неверен, ответ на ваш вопрос технически да. Но этого можно добиться только с помощью неприятных уловок, которые сделают ваш код нечитаемым и непригодным для сопровождения.
См. также: http://www.ioccc.org/years.html#1995_vanschnitz и http://www.ioccc.org/years.html#2004_vik2
Нет, вы не можете этого сделать.
Символ фунта стерлингов (#
) имеет другое значение в определении. это означает - если это аргумент, сделайте его строкой, заключив в кавычки.
Вы не можете вкладывать директивы препроцессора C. К счастью, это почти никогда не требуется. Если вам действительно нужна такая мощность, вам почти наверняка будет лучше использовать другой препроцессор, который вы запускаете перед передачей кода компилятору C. Например:
sed 's/@CUSTOMER@/J. Random Person/' foo.c.in > foo.c
cc foo.c
Еще один полезный прием — изолировать обман в один заголовочный файл, который генерируется программой, которую вы пишете сами:
./generate-trickery --greet 'J. Random Person' > foo.h
где foo.h будет выглядеть примерно так:
#define GREET(x) ("J. Random Person greets you, " #x)
Если вы свяжете это вместе с Makefile или какой-либо другой автоматизацией, это будет довольно гладко и не сильно затруднит вашу разработку.
Нет, ты не можешь этого сделать.
Вы можете ссылаться на один макрос из другого, но вы не можете определить один макрос из другого.
Если вы пытаетесь создать сегмент кода препроцессора, который можно вызывать несколько раз для выполнения немного разных действий, один (умеренно ужасный) способ сделать это — изолировать код в один файл .h
, который вы затем #include
несколько раз. Идея состоит в том, что каждый раз, когда вы #include
вызываете файл, вы "вызываете свою процедуру" -- вы "передаете аргументы", сначала #define
вводя определенные константы препроцессора, на которые ссылается включенный файл.
Одно место, где я видел, что это полезно, - это создание "умных" перечислений, которые могут преобразовываться в/из их "строковых" форм (что полезно для ввода-вывода). Вы создаете файл .h
, содержащий, например.
ENUMVAL(foo)
ENUMVAL(bar)
ENUMVAL(baz)
а затем позже #include
этот файл дважды: один раз, когда ENUMVAL()
определяется таким образом, чтобы создать объявление enum
, и один раз, когда ENUMVAL()
определяется таким образом, чтобы создать массив строковых имен. Делая это таким образом, вам не нужно указывать список фактических токенов более одного раза.
#define definer(x) #define #x?
#x — это строковое обозначение x. Вы не можете #define строковый токен. (#define "foo".) Это должен быть токен идентификатора [a-zA-Z0-9_]*.
Вы не можете вкладывать #define таким образом. У вас не может быть #define в #define.
Вы можете иметь #if внутри блоков #if.
#ifdef FOO
#ifdef BAR
...
#else // BAR
...
#endif // BAR
#else // FOO
...
#endif //FOO
Вы также несколько ограничены в выражениях, которые вы можете использовать в макросах #if. Но иногда можно обойти это. Например:
/* Use CONCATENATESTATIC_ASSERT( sizeof(int1) == 1, sizeof_int1_equal_1 );
AGAIN to expand the arguments to CONCATENATE_4 */
#define CONCATENATE_4( a,b,c,d) CONCATENATESTATIC_ASSERT( sizeof(int1) == 1, sizeof_int1_equal_1 );
AGAIN(a,b,c,d)
#define CONCATENATESTATIC_ASSERT( sizeof(int1) == 1, sizeof_int1_equal_1 );
AGAIN(a,b,c,d) a ## b ## c ## d
/* Creates a typedef that's legal/illegal depending on EXPRESSION. *
* Note that IDENTIFIER_TEXT is limited to "[a-zA-Z0-9_]*". *
* (This may be replaced by static_assert() in future revisions of C++.) */
#define STATIC_ASSERT( EXPRESSION, IDENTIFIER_TEXT) \
typedef char CONCATENATE_4( static_assert____, IDENTIFIER_TEXT, \
____failed_at_line____, __LINE__ ) \
[ (EXPRESSION) ? 1 : -1 ]
Плюс что-то вроде:
STATIC_ASSERT( sizeof(int1) == 1, sizeof_int1_equal_1 );
(Да, я знаю о #include ‹stdint.h›. Это просто пример.)