Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Preprocessor & оператор "##"
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
AndryG
Доброго.
Есть кусок (подсмотрел оператор ## в коде у народа) кода
Код
#define STX_PORT_NAME       B
#define STX_PIN             3

#define STX_CONCAT(a,b)     a ## b
#define STX_GEN_PORT(name)  STX_CONCAT(PORT,name)
#define STX_GEN_DDR(name)   STX_CONCAT(DDR ,name)
#define STX_PORT            STX_GEN_PORT(STX_PORT_NAME)
#define STX_DDR             STX_GEN_DDR (STX_PORT_NAME)

#define stx_init()          {STX_PORT |= (1<<STX_PIN);\
                              STX_DDR  |= (1<<STX_PIN);}
Всё компилится.
Но хочется избавится от макросов STX_GEN_x и STX_CONCATE
Код
#define STX_PORT  PORT ## STX_PORT_NAME
   превращается
Error[Pe020]: identifier "PORTSTX_PORT_NAME" is undefined D:\step_f\step_f.c 58


Откройте секрет, пжлст, как оператору ## толком указать, где "значение", а где "переменная", значение которой надо вставить.
Палыч
Цитата(AndryG @ Dec 25 2009, 18:23) *
Откройте секрет, пжлст, как оператору ## толком указать, где "значение", а где "переменная", значение которой надо вставить.
С помощью макросов, от которых Вы желаете избавиться, "значения" "переменных" передаются оператору ##
zltigo
Цитата(AndryG @ Dec 25 2009, 18:23) *
Откройте секрет, пжлст, как оператору ## толком указать, где "значение", а где "переменная", значение которой надо вставить.

http://masterpc.alfaspace.net/books/CCScie...ramming/4/#p411
AndryG
Код
#define STX_PORT            STX_CONCAT(PORT,STX_PORT_NAME)
  
  Error[Pe020]: identifier "PORTSTX_PORT_NAME" is undefined D:\step_f\step_f.c 59

Не доходит до меня ... почему это не работает?
Даю я ему два параметра ... оператору ## должны придти две лексемы PORT и B

Почему не раскрывается значение STX_PORT_NAME и надо городить
Код
#define STX_CONCAT(a,b)     a ## b
  #define STX_GEN_PORT(name)  STX_CONCAT(PORT,name)
  #define STX_PORT            STX_GEN_PORT(STX_PORT_NAME)


____
P.S.
Пропустил ответ zltigo. Ушёл читать smile.gif
Упустил я сей момент в свое время у Кернигана...

http://masterpc.alfaspace.net/books/CCScie...amming/a/#a12_3
Цитата
Если макроопределение было задано вторым способом, то текстовая последовательность, состоящая из его идентификатора, возможно, со следующими за ним символами-разделителями, знака (, списка лексем, разделенных запятыми, и знака ), представляет собой вызов макроса. Аргументами вызова макроса являются лексемы, разделенные запятыми (запятые, "закрытые" кавычками или вложенными скобками, в разделении аргументов не участвуют). Аргументы при их выделении макрорасширениям не подвергаются. Количество аргументов в вызове макроса должно соответствовать количеству параметров макроопределения. После выделения аргументов окружающие их символы-разделители выбрасываются. Затем в замещающей последовательности лексем макроса идентификаторы-параметры (если они не закавычены) заменяются на соответствующие им аргументы. Если в замещающей последовательности перед параметром не стоит знак # и ни перед ним, ни после него нет знака ##, то лексемы аргумента проверяются: не содержат ли они в себе макровызова, и если содержат, то прежде чем аргумент будет подставлен, производится соответствующее ему макрорасширение.

На процесс подстановки влияют два специальных оператора. Первый -это оператор #, который ставится перед параметром. Он требует, чтобы подставляемый вместо параметра и знака # (перед ним) текст был заключен в двойные кавычки. При этом в строковых литералах и символьных константах аргумента перед каждой двойной кавычкой " (включая и обрамляющие строки), а также перед каждой обратной наклонной чертой \ вставляется \.

Второй оператор записывается как ##. Если последовательность лексем в любого вида макроопределении содержит оператор ##, то сразу после подстановки параметров он вместе с окружающими его символами-разделителями выбрасывается, благодаря чему "склеиваются" соседние лексемы, образуя тем самым новую лексему. Результат не определен при получении неправильных лексем или когда генерируемый текст зависит от порядка применения операторов ##. Кроме того, ## не может стоять ни в начале, ни в конце замещающей последовательности лексем.


Это здесь ... но надо вникнуть ...


Заготовка для примера.
Код
#define STX_PORT_NAME       B
#define STX_PIN             3

#define STX_PORT_(name)     PORT ## name
#define STX_PORT__(name)    STX_PORT_(name)
#define STX_PORT            STX_PORT__(STX_PORT_NAME)


Код
STX_PORT_(STX_PORT_NAME) |=  (1<<STX_PIN);
Получаем
Error[Pe020]: identifier "PORTSTX_PORT_NAME" is undefined D:\step_f\step_f.c 84
Ибо! STX_PORT_NAME, как параметр, передается в
#define STX_PORT_(name) PORT ## name,
а там возле name стоит ## и превращения STX_PORT_NAME => B не происходит.

Код
STX_PORT__(STX_PORT_NAME) |=  (1<<STX_PIN);

Всё скомпилилось
Ибо! В макросе
#define STX_PORT STX_PORT__(STX_PORT_NAME)
нет ## и STX_PORT_NAME превратилось в B
дальше идет вызов #define STX_PORT__(name) с значением параметра уже B, а не STX_PORT_NAME ...
и дальше по накатанной.

И в итоге получил вот такое:
Код
#define STX_PORT_NAME       B
#define STX_PIN             3

#define STX_CONCAT(a,b)     a ## b
#define STX_CONCAT2(a,b)    STX_CONCAT(a,b)
#define STX_PORT            STX_CONCAT2(PORT,STX_PORT_NAME)
#define STX_DDR             STX_CONCAT2(DDR,STX_PORT_NAME)

#define stx_init()          {STX_PORT |= (1<<STX_PIN);\
                             STX_DDR  |= (1<<STX_PIN);}
demiurg_spb
Наберите в google "Макросы имени Аскольда Волкова"...
http://electronix.ru/forum/index.php?showt...st&p=524439
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.