Стрификация значения переменной - PullRequest
2 голосов
/ 10 ноября 2011
#define SATA_PORT_0   "/sata-ahci/port0"
#define SATA_PORT_1   "/sata-ahci/port1"
#define SATA_PORT_2   "/sata-ahci/port2"
#define SATA_PORT_3   "/sata-ahci/port3"
#define SATA_PORT_4   "/sata-ahci/port4"
#define SATA_PORT_5   "/sata-ahci/port5"

#define SATA_NODE(p)  HOW TO DEFINE THIS?!!

int main() 
{
    int i;
    for (i=0;i<6;i++)
    {
        printf("%s\n", i, SATA_NODE(i));
    }
    return 0;
}

Вопрос: как определить макрос выше, чтобы вывести строку в GCC?

Ответы [ 5 ]

2 голосов
/ 10 ноября 2011

Вы не можете легко сделать это с помощью макроса.

Проблема в том, что макрос - это конструкция времени компиляции, а у вас есть цикл времени исполнения; Вы не можете сделать это напрямую.

Вы можете исследовать Boost Preprocessor (который не предназначен специально для C ++; он также работает с препроцессором C) и использовать его для написания макросов, которые генерируют цикл.

Вы можете вручную развернуть цикл и использовать макрос с постоянным аргументом:

#define SATA_PORT(i) "/sata-ahci/port" #i

printf("%s\n", 0, SATA_PORT(0));
printf("%s\n", 1, SATA_PORT(1));
printf("%s\n", 2, SATA_PORT(2));
printf("%s\n", 3, SATA_PORT(3));
printf("%s\n", 4, SATA_PORT(4));
printf("%s\n", 5, SATA_PORT(5));

Или вы можете использовать массив строк (также предложенный удаленным ответом).

#define DIM(x) (sizeof(x)/sizeof(*(x)))

const char * const sata_ports[] = 
{
    "/sata-ahci/port0",
    "/sata-ahci/port1",
    "/sata-ahci/port2",
    "/sata-ahci/port3",
    "/sata-ahci/port4",
    "/sata-ahci/port5"
};

for (int i = 0; i < DIM(sata_ports); i++)
    printf("%d %s\n", i, sata_ports[i]);
1 голос
/ 10 ноября 2011

На языке Си вы не можете. Подстановка макроса происходит перед обычной компиляцией. Препроцессор не знает, что токен предварительной обработки i будет объявлен как int позже во время обычной компиляции.

Казнь приходит еще позже. Компилятор может выяснить, что у меня будут значения в диапазоне от 0 до 5, но это вам не поможет. Фактические назначения происходят во время выполнения, то есть после завершения компиляции, то есть после завершения предварительной обработки.

0 голосов
/ 04 марта 2013

Может быть, это то, что вам нужно (ред.):

#define STRINGIFY(x)                #x
#define TOSTRING(x)                 STRINGIFY(x)
#define SATA_NODE_TO_SATA_PORT(p)   SATA_PORT_##p
#define SATA_NODE(p)                TOSTRING(SATA_NODE_TO_SATA_PORT(p))

Затем, если вы попытаетесь напечатать предварительно обработанные макросы с помощью:

std::cout << SATA_NODE(3) << " - " << SATA_NODE(5) << std::endl;
std::cout << SATA_NODE(7) << std::endl;

что вы получаете:

"/sata-ahci/port3" - "/sata-ahci/port5"
SATA_PORT_7
0 голосов
/ 14 ноября 2011

РЕДАКТИРОВАТЬ: Я сделал решение немного лучше (из-за доступности составных операторов в компиляторе GCC).

Если у меня была похожая проблема, ярешит это так:

#define SATA_PORT(p) ({char prt[100]; sprintf(prt, "/sata-ahci/port%d", p); prt;})

И кстати, вы забыли printf спецификатор формата для переменной i.

0 голосов
/ 14 ноября 2011

Спасибо за ответы выше.Я нашел способ сделать это сам.

#define SATA_PORT(p) (p==0)?SATA_PORT_0:ISP1
#define ISP1         (p==1)?SATA_PORT_1:ISP2
...

В некоторых ситуациях приведенный выше макрос делает код намного лучше.

...