реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Preprocessor & оператор "##", Как сложить оператор из букв ?
AndryG
сообщение Dec 25 2009, 15:23
Сообщение #1


Частый гость
**

Группа: Свой
Сообщений: 139
Регистрация: 23-05-05
Из: UA
Пользователь №: 5 317



Доброго.
Есть кусок (подсмотрел оператор ## в коде у народа) кода
Код
#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


Откройте секрет, пжлст, как оператору ## толком указать, где "значение", а где "переменная", значение которой надо вставить.
Go to the top of the page
 
+Quote Post
Палыч
сообщение Dec 25 2009, 15:33
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(AndryG @ Dec 25 2009, 18:23) *
Откройте секрет, пжлст, как оператору ## толком указать, где "значение", а где "переменная", значение которой надо вставить.
С помощью макросов, от которых Вы желаете избавиться, "значения" "переменных" передаются оператору ##
Go to the top of the page
 
+Quote Post
zltigo
сообщение Dec 25 2009, 15:49
Сообщение #3


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



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

http://masterpc.alfaspace.net/books/CCScie...ramming/4/#p411


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
AndryG
сообщение Dec 25 2009, 16:53
Сообщение #4


Частый гость
**

Группа: Свой
Сообщений: 139
Регистрация: 23-05-05
Из: UA
Пользователь №: 5 317



Код
#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);}
Go to the top of the page
 
+Quote Post
demiurg_spb
сообщение Dec 26 2009, 09:52
Сообщение #5


неотягощённый злом
******

Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643



Наберите в google "Макросы имени Аскольда Волкова"...
http://electronix.ru/forum/index.php?showt...st&p=524439


--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 19th July 2025 - 04:39
Рейтинг@Mail.ru


Страница сгенерированна за 0.01401 секунд с 7
ELECTRONIX ©2004-2016