Вопрос

Например, возможно ли следующее:

#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 несколько раз. Идея заключается в том, что каждый раз, когда вы #define файл <<>>, вы «вызываете свою подпрограмму & Quot; - вы " передаете аргументы " сначала ENUMVAL() определив константы препроцессора, на которые ссылается включаемый файл.

Одно из мест, где я видел это полезным, - генерация " smart " перечисления, которые можно преобразовать в / из их " stringized " формы (что полезно для ввода / вывода). Вы создаете enum файл, содержащий, например,

.
ENUMVAL(foo)
ENUMVAL(bar)
ENUMVAL(baz)

, а затем <=> этот файл дважды: один раз, где <=> определяется таким образом, чтобы создать объявление <=>, и один раз, когда <=> определяется таким образом, чтобы создать массив строковых имен. Делая это таким образом, вам не нужно указывать список фактических токенов более одного раза.

#define definer(x) #define #x?

#x - это строка x. Вы не можете # определить строковый токен. (#define " foo " ;.) Это должен быть идентификатор [a-zA-Z0-9 _] * токен.

Вы не можете вложить # определить это так. Вы не можете иметь #define в #define.

Вы можете иметь # if внутри #if блоков.

#ifdef FOO

#ifdef BAR
 ...
#else // BAR
 ...
#endif // BAR

#else // FOO
 ...
#endif //FOO

Вы также несколько ограничены в выражениях, которые вы можете использовать в #if макросах. Но иногда вы можете обойти это. Например:

        /* Use CONCATENATE_4_AGAIN to expand the arguments to CONCATENATE_4 */
#define CONCATENATE_4(      a,b,c,d)  CONCATENATE_4_AGAIN(a,b,c,d)
#define CONCATENATE_4_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 > . Это всего лишь пример.)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top