C++ 对另一个宏输出使用##预处理器运算符
我正在尝试使用##预处理器操作符来确定要使用的GPIO。 这是我的密码:C++ 对另一个宏输出使用##预处理器运算符,c++,c,macros,preprocessor,C++,C,Macros,Preprocessor,我正在尝试使用##预处理器操作符来确定要使用的GPIO。 这是我的密码: #define GPIO_Pin_1 0x0001 #define GPIO_Pin_2 0x00CA #define GPIO_Pin_3 0x00DE #define GPIO_Pin_4 0x00AC #define DIVIDE(a , b) ( (a) / (b) ) #define NUMBER_TO_GPIO(a) GPIO_Pin_##DIVIDE(a , 2) int gpioNumber = 8;
#define GPIO_Pin_1 0x0001
#define GPIO_Pin_2 0x00CA
#define GPIO_Pin_3 0x00DE
#define GPIO_Pin_4 0x00AC
#define DIVIDE(a , b) ( (a) / (b) )
#define NUMBER_TO_GPIO(a) GPIO_Pin_##DIVIDE(a , 2)
int gpioNumber = 8;
int gpioAddress = NUMBER_TO_GPIO(gpioNumber);
gpioAddress的期望值是0x00AC(GPIO_引脚_4),但编译器给出了此错误:“GPIO_引脚_DIVIDE隐式声明”。我想将GPIO和除法(a,b)宏的结果合并到符号中。因此,您形成了一个未知的符号
GPIO\u Pin\u DIVIDE
你能做的是:
#define GPIO_Pin_1 0x0001
#define GPIO_Pin_2 0x00CA
#define GPIO_Pin_3 0x00DE
#define GPIO_Pin_4 0x00AC
#define DIVIDE(a , b) ( (a) / (b) )
#define NUMBER_TO_GPIO(a) (DIVIDE( GPIO_Pin_##a , 2))
int gpioAddress = NUMBER_TO_GPIO(4);
但我不确定这是否是您的意思。如评论中所述,您的宏无法工作。您可以使用数组:
const int GPIO_Pins[] = {
/*GPIO_Pin_1*/ 0x0001,
/*GPIO_Pin_2*/ 0x00CA,
/*GPIO_Pin_3*/ 0x00DE,
/*GPIO_Pin_4*/ 0x00AC
};
#define NUMBER_TO_GPIO(a) GPIO_Pins[(a) / 2 - 1]
当然,问题是没有边界检查。在C++中,< P>,使用CONTHEXPR计算编译时的值。
static constexpr std::array<int, 4> Pins = { 0x01, 0x0A, 0xDE, 0xAC };
static constexpr int pin2(int a)
{
return Pins[a / 2];
}
static constepr std::array Pins={0x01,0x0A,0xDE,0xAC};
静态constexpr int pin2(int a)
{
回位销[a/2];
}
仅使用CPP无法实现您想要实现的目标。尤其是在运行时计算GPIO数时
确保它在编译时是直接替换的唯一方法是直接使用索引(您没有这样做)
将此视为C中的解决方案:
const long GPIO_PINS[] = { 0xFFFF, 0x0001, 0x00CA, 0x00DE, 0x00AC };
static inline long getGPIOAddr(int gpioAddress) {
return GPIO_PINS[gpioAddress >> 1];
}
int main() {
const int gpioNumber = 8;
return getGPIOAddr(gpioNumber);
}
以下是gcc的汇编输出(clang给出了类似的结果):
gcc-S-O foo.c
为了完整起见,这里是叮当声:
.file "foo.c"
.text
.globl main
.align 16, 0x90
.type main,@function
main: # @main
.cfi_startproc
# BB#0:
movl $172, %eax
ret
.Ltmp0:
.size main, .Ltmp0-main
.cfi_endproc
.type GPIO_PINS,@object # @GPIO_PINS
.section .rodata,"a",@progbits
.globl GPIO_PINS
.align 16
GPIO_PINS:
.quad 65535 # 0xffff
.quad 1 # 0x1
.quad 202 # 0xca
.quad 222 # 0xde
.quad 172 # 0xac
.size GPIO_PINS, 40
.ident "clang version 3.4.2 (tags/RELEASE_34/dot2-final)"
.section ".note.GNU-stack","",@progbits
任何优秀的现代编译器都可以确定gpioNumber在特定AST期间不会发生变化,并将正确地替换常量
因此,不要试图智取编译器,它在优化方面比你强得多
如果您对编译器在这方面的出色程度感兴趣,我已经在godbolt加载了以下代码:
您可以尽情地查看代码的反汇编。那里的所有编译器都使用a-O作为选项来优化这些内容。“我想计算GPIO引脚和除法(a,b)宏的结果”您对除法的结果有什么期望?你需要一个数值吗?`C预处理器进行文本替换。不是数学评估。结果将是
((gpioNumber)/(2))
,这不适合任何串联尝试。为什么不使用函数?请确定您使用的是哪种语言?你同时添加了C和C++,但是你只能一次使用一个。每当你为一些简单的东西想出复杂的宏,比如设置一个GPIO PIN,你就知道你的程序设计已经过时了。很可能这是一个XY问题,您不应该首先使用宏来解决它。例如,这闻起来像一个简单的查找表会很方便。这不完全是我想要的,但它是有用的。如果我不能解决我的问题,我会试试这个。在预处理过程中,输出是intgpioaddress=((0x00AC)/(2))代码>而对于使用8的宏调用,所需的输出是int-gpioAddress=0x00AC代码>。您不再需要除法,因为您已经手动将8改为4(在源代码中)。因此,使用修改后的参数,#define NUMBER_TO_GPIO(a)GPIO#u Pin#a
就足够了。你是对的。我以为目标是更正地址,但目标是索引。谢谢你的回答,但这不是我想要的。我不会把地址分开。地址是恒定的。我正在尝试确定我将用于初始化GPIO的巫婆地址
.file "foo.c"
.text
.globl main
.align 16, 0x90
.type main,@function
main: # @main
.cfi_startproc
# BB#0:
movl $172, %eax
ret
.Ltmp0:
.size main, .Ltmp0-main
.cfi_endproc
.type GPIO_PINS,@object # @GPIO_PINS
.section .rodata,"a",@progbits
.globl GPIO_PINS
.align 16
GPIO_PINS:
.quad 65535 # 0xffff
.quad 1 # 0x1
.quad 202 # 0xca
.quad 222 # 0xde
.quad 172 # 0xac
.size GPIO_PINS, 40
.ident "clang version 3.4.2 (tags/RELEASE_34/dot2-final)"
.section ".note.GNU-stack","",@progbits