LINUX.ORG.RU

Объединение токенов в препроцессоре Си

 ,


0

3

Я знаю, что там есть подводные камни (что надо объявить несколько макросов, нельзя просто склеить два токена).

Итак, имею следующие макроопределения в обоих проектах:

#define CONCAT(a, b) a ## b
#define CONCAT_EXPANDED(a, b) CONCAT(a, b)

А теперь код в одном проекте:

#define LED_PORT C
...
#define DDR(name) CONCAT(DDR, name)
...
#define LED_DDR DDR(LED_PORT)

Код в другом проекте:

#define GPS_USART USART2
...
#define RCC(name) CONCAT(RCC_, name)
...
#define GPS_USART_RCC RCC(GPS_USART)

В первом случае всё нормально компилируется, во втором препроцессор выдаёт ошибку при попытке использования:

ошибка: pasting "RCC_" and "(" does not give a valid preprocessing token
 #define RCC(name) CONCAT(RCC_, name)
                                   ^
предупреждение: implicit declaration of function 'RCC_' [-Wimplicit-function-declaration]
 #define RCC(name) CONCAT(RCC_, name)
                          ^

Если скопипастить код из первого проекта во второй, то в нём ошибку препроцессора он вызывать не будет (точнее вызовет ошибку доступа к несуществующему символу DDRC, но это уже совсем другой разговор - проект то другой).

То есть вообще магия получается. Я в упор не вижу, чем эти два варианта кода отличаются. Точнее догадываюсь («USART2» - объявленное макроопределение, а «C» - нет), но не знаю как с этим бороться.

★★★★★

Последнее исправление: KivApple (всего исправлений: 3)
Ответ на: комментарий от t184256

А его и нет. Я ожидаю получить на выходе токен RCC_USART2, который уже объявлен в библиотеки с помощью define.

И мне не стоит разворачивать RCC_ и USART2 до склейки, потому что я хочу склеить именно эти два токена, а уже потом развернуть результат.

KivApple ★★★★★
() автор топика
Последнее исправление: KivApple (всего исправлений: 2)
Ответ на: комментарий от KivApple

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

Ну так говорю же тебе, юзай свой CONCAT_EXPANDED.

#define MEGA_TOKEN 42
#define X MEGA_
#define Y TOKEN
#define CONCAT(a, b) a ## b
#define CONCAT_EXPANDED(a, b) CONCAT(a, b)

X ## Y
CONCAT(X, Y)
CONCAT_EXPANDED(X, Y)

CONCAT(MEGA_, Y)
CONCAT_EXPANDED(MEGA_, Y)
XY
42

MEGA_Y
42
t184256 ★★★★★
()
Ответ на: комментарий от t184256
#define MEGA_ Z

#define MEGA_TOKEN 42
#define X MEGA_
#define Y TOKEN
#define CONCAT(a, b) a ## b
#define CONCAT_EXPANDED(a, b) CONCAT(a, b)

X ## Y
CONCAT(X, Y)
CONCAT_EXPANDED(X, Y)

CONCAT(MEGA_, Y)
CONCAT_EXPANDED(MEGA_, Y)
XY
ZTOKEN

MEGA_Y
ZTOKEN

А это как раз мой случай. USART2 - объявленное макроопределение. Как и RCC_USART2. Мне нужно как-то сделать, чтобы развёртывание произошло только после склеивания токенов.

KivApple ★★★★★
() автор топика
Ответ на: комментарий от KivApple

Судя по твому примеру я вижу, что ты хочешь развертывание второго аргумента, неразвертывание первого и развертывание итога. Я че-то бился-бился и не смог сделать неразвертывание MEGA_ без моментальной приконкатенации куда попало. Отсюда два вывода:

1) тупо не делай #define MEGA_ (или что у тебя там, RCC_?)

2) ты хочешь хрень настолько неочевидную, что ее за два поста не объяснить! ее поддерживаемость равна нулю, тупо не пиши ее!

t184256 ★★★★★
()

tdlr. stringify?

anonymous
()
Ответ на: комментарий от Kuzy

Function macros are more powerful and you can delay the expansion of them. Here's how you can delay them for one scan

Черт. Мне приходило это в голову, но че-то не получилось. Но это, ТС, все равно не делай так, иначе твои последователи тебя до гробовой доски проклянут.

t184256 ★★★★★
()

что-то такое, не?

#include <stdio.h>
#include <stdlib.h>

#define CONCAT(a, b) a ## b
#define CONCAT_EXPANDED(a, b) CONCAT(a, b)

#define USART2 "bla-bla"
#define RCC_USART2 42

#define GPS_USART _USART2

#define RCC(x) RCC ## x

#define XRCC(x) RCC(x)
#define GPS_USART_RCC XRCC(GPS_USART)

int main()
{
    printf("%d %s\n",GPS_USART_RCC, USART2);
    return 0;
}

Iron_Bug ★★★★★
()
Ответ на: комментарий от Iron_Bug

*собна, конкаты у меня не используются, но можно через них написать.

Iron_Bug ★★★★★
()
Ответ на: комментарий от Iron_Bug
printf("%d %s\n", GPS_USART_RCC, GPS_USART);

Я ожидаю получить то же, что и в твоём варианте, а получу ошибку необъявленного _USART2. Мне GPS_USART нужен не только для склейки, но и непосредственно для использования.

KivApple ★★★★★
() автор топика
Ответ на: комментарий от KivApple
#include <stdio.h>
#include <stdlib.h>

#define USART2 "bla-bla"
#define RCC_USART2 42

#define GPS_USART USART2
#define _GPS_USART _USART2

#define RCC(x) RCC ## x

#define XRCC(x) RCC(x)
#define GPS_USART_RCC XRCC(_GPS_USART)

int main()
{
    printf("%d %s\n",GPS_USART_RCC, GPS_USART);
    return 0;
}

Iron_Bug ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.