Как объединить два или более целых чисел с помощью макросов? - PullRequest
2 голосов
/ 25 июня 2010

Если a = 1, b = 2, c = 3 ... Я хотел бы написать макрос, который объединяет их следующим образом 123. Но когда я пытаюсь это сделать:

#include<stdio.h>
#define cat(a,b,c) a##b##c

int main()
{
int a=1,b=2,c=3,d;
d=cat(1,2,3); //Works
d=cat(a,b,c); // Returns an error...How to make this work?
return 0;
}

Ответы [ 8 ]

10 голосов
/ 25 июня 2010

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

3 голосов
/ 25 июня 2010

макросы определения хэша - это время до компиляции и они предварительно обрабатываются перед компиляцией.Препроцессор не будет иметь доступа к значениям переменных.d=cat(a,b,c) будет преобразован в d=abc препроцессором.

Вам нужно будет использовать itoa или что-то подобное и объединить получившиеся строки, а затем снова вернуться к ним.некоторая арифметика, чтобы выяснить результат.

1 голос
/ 25 июня 2010

Если это не важно, что это делается во время компиляции, вы можете использовать что-то вроде этого:

#include <math.h>
unsigned intcat(unsigned a, unsigned b, unsigned c)
{
    unsigned dlogc = 1 + (unsigned)(log(c)/log(10));
    unsigned dlogb = 1 + (unsigned)(log(b)/log(10));
    return (unsigned)(c + pow(10,dlogc) * b + pow(10,dlogb+dlogc) * a);
}

Я не знаю, есть ли что-нибудь в библиотеках наддува для выполнения такой математики во время компиляциииспользуя TMP.

1 голос
/ 25 июня 2010

Это может быть отправной точкой:

#include <stdio.h>

#define cat(x,a,b,c) snprintf(x, sizeof(x), "%d%d%d", a, b, c)

main(int argc, char *argv[])
{
    char s[20];
    cat(s, 4,5,6);
    printf("%s\n", s);
}
1 голос
/ 25 июня 2010

Строковое преобразование препроцессора не может работать с переменными, оно должно принимать литерал и преобразовывать его в строку во время обработки; препроцессор не знает, что равняется a, b и c в вашем вызове cat(). Вам нужно написать макрос, который на самом деле использует C ++ для объединения. Например:

#define cat(a, b, c, d) \
    do { \
        std::stringstream ss; \
        ss << a << b << c; \
        ss >> d; \
    } while(0)

(do/while(0) - это обычный хак, позволяющий добавить точку с запятой после безопасного вызова cat)

Вы не сможете использовать «возвращаемое значение» из этого, но вы можете сделать:

int a = 1, b = 2, c = 3, d;
cat(a, b, c, d);
// d == 123 now
0 голосов
/ 13 ноября 2013

Вы также можете использовать эту функцию для объединения 3 целых (другая приведенная выше функция intcat не работает, когда 0 - это вторая или третья цифра. Это потому, что лог 0 является отрицательной бесконечностью, а когда вы передаете 0, он вычитает 1 из вашего общего числа).

unsigned intcat(unsigned a, unsigned b, unsigned c)
{

uint8_t ax = a;

uint8_t bx = b;

uint8_t cx = c;

ax = (ax * 100);

bx = (bx * 10);

cx = (cx * 1);

return(ax + bx + cx);

}
0 голосов
/ 07 сентября 2013

Возможно для целых чисел, определенных препроцессором.
Препроцессору нужен вызов другой функции для расширения.
Вы делаете это следующим образом:

#define I_BASE_CONCAT(x,y) x ## y
#define I_CONCAT(x,y) I_BASE_CONCAT(x,y)

Вот оно. Теперь, если вы вызовете I_CONCAT, он расширит его до x ## y, но со значениями x и y.

0 голосов
/ 25 июня 2010

Препроцессор C делает просто фиктивную замену текста в время компиляции .

Что означает подстановка текста ? Препроцессор выведет код C, заменяя параметры макроса переданными значениями. Неважно, передадите ли вы переменную или постоянное число, вы просто получите фиктивную подстановку (также называемую макросом «расширение»).

Давайте посмотрим, как препроцессор будет «расширяться» #define cat(a,b,c) a##b##c.

d=cat(1,2,3); расширяется до: d=123;, и это действительный код, поскольку вы объявили int d.

d=cat(a,b,c); расширяется до: d=abc;, и это не скомпилируется, так как нет переменной int abc.

Что означает время компиляции ? Это означает, что эта подстановка текста выполняется в исходном коде, а вывод игнорирует содержимое переменных, передаваемых в макрос. Другими словами, не имеет значения, что вы инициализировали a, b и c до 1, 2 и 3: результатом будет только конкатенация (из-за ## оператор препроцессора "вставка токена") переданных значений. В вашем случае результат будет abc, что ничего не значит в вашем коде.

...