Как объединить и оценить макрос с помощью оператора ##

#c #macros

#c #макросы

Вопрос:

Я написал код на C, подобный этому

 #include<stdio.h>
#include<stdint.h>
#define CHAN(n) ((0x8020##4 n) ## 20)
void main()
{
     int n = any_value;
     printf("%x",CHAN(n));
}
 

Я получаю ошибку компиляции pasting ")" and "20" does not give a valid preprocessing token .

На самом деле я хочу оценить выражение со значением n . Итак, допустим, если я передаю значение n as 1 , чем я ожидаю вывода 0x8020520 . Аналогично, если я передаю значение n as 8 , чем я ожидаю 0x8020c20 .

Если я удаляю ##20 из макроса, я не получаю никакой ошибки компиляции и получаю ожидаемый половинный результат, например 0x80205 , или 0x8020c Моя проблема в том, что я не могу найти способ объединить 20 после вычисления выражения (0x8020##4 n)##20 , т.е. Любая помощь будет оценена.

Комментарии:

1. Это не то, как работает препроцессор (он не может добавлять, а затем вставлять). В зависимости от вашего полного макроса это можно легко заменить некоторой математикой: CHAN(n) (0x8020020 | ((4 (n)) << 8))

2. @Artyer: Вы можете сделать это ответом.

3. «Итак, допустим, если я передам значение n как 1, то я ожидаю вывода 0x8020520. Аналогично, если я передаю значение n как 4, чем я ожидаю 0x8020c20» Какой в этом смысл? Что здесь переменная, сдвиги или значения? Это не может быть и то, и другое одновременно. Эти два предложения противоречат друг другу.

4. @Lundin на самом деле 0x8020(4 n)20 является базовым адресом. Если я хочу вычислить следующий адрес, то это зависит от значения n . Я имею в виду, если я передаю значение n как 1, чем оно становится 0x8020(4 1)20=0x8020520 . Аналогично, если мы передадим 8 , чем это станет 0x8020(4 8)20=0x8020c20

5. Но вы написали «если я передам значение n как 4, то я ожидаю 0x8020c20». Должно ли быть указано n = 8? Пожалуйста, отредактируйте и исправьте.

Ответ №1:

Когда вы это делаете (0x8020##4 n) , он анализируется как эти токены: «(«, «0x8020» ## «4», » «, » n», «)».

После вставки «0x8020» и «4» вместе вы получаете ( 0x80204 n ) . На самом деле это не добавляется n перед вставкой. (И как это могло быть? Препроцессор не знает, что такое переменная, и считает, что «n» — это просто строка длиной 1)

Когда вы это делаете ) ## 20 , вы получаете недопустимый токен «) 20», что не имеет смысла. Таким образом, он по праву выдает ошибку.

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

  #define CHAN(n) (0x8020020 | ((4   n) << 8))
 //                     ^
 

(Где сдвиг перемещает единственную шестнадцатеричную цифру, представленную (4 n), на значение второго места, и | (побитовое или)-ing оно заменит указанное 0.

Комментарии:

1. Я думаю, мы должны << использовать 8 вместо 4

2. Но это не дает «если я передам значение n как 4, чем я ожидаю 0x8020c20». n = 4 дает 8020820 . Оказывается, вопрос не имеет никакого смысла и на него нельзя ответить.