Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/shell/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 对另一个宏输出使用##预处理器运算符_C++_C_Macros_Preprocessor - Fatal编程技术网

C++ 对另一个宏输出使用##预处理器运算符

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;

我正在尝试使用##预处理器操作符来确定要使用的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;
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