【问题标题】:C Macro concatenation as function argumentC 宏连接作为函数参数
【发布时间】:2015-06-30 13:51:58
【问题描述】:

我在使用宏作为函数参数时遇到问题。

我有这个宏:

#define PD13 GPIOD, GPIO_Pin_13

GPIODGPIO_Pin_13 也是宏。

#define GPIO_Pin_13 ((uint16_t)0x2000)
#define GPIOD  ((GPIO_TypeDef *) GPIOD_BASE)

其中GPIOD_BASE是一个内存地址。

我用它作为这个函数的参数:

PinType initPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) {
PinType pin;
if (GPIOx == GPIOA) {
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
} else if (GPIOx == GPIOB) {
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
} else if (GPIOx == GPIOC) {
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
} else if (GPIOx == GPIOD) {
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
} else {
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
}
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOx, &GPIO_InitStructure);
GPIO_ResetBits(GPIOx, GPIO_Pin);
pin.GPIO_Reg = GPIOx;
pin.GPIO_Pin = GPIO_Pin;
pin.status = 1;
return pin;
}
PinType p1
p1 = initPin(PD13);

这样一切正常,但如果我尝试向initPin 函数添加一个参数,例如:

void initPin(PinType *pin, GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) {
if (GPIOx == GPIOA) {
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
} else if (GPIOx == GPIOB) {
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
} else if (GPIOx == GPIOC) {
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
} else if (GPIOx == GPIOD) {
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
} else {
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
}
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOx, &GPIO_InitStructure);
GPIO_ResetBits(GPIOx, GPIO_Pin);
pin->GPIO_Reg = GPIOx;
pin->GPIO_Pin = GPIO_Pin;
pin->status = 1;
}

PinType p1;
initPin(&p1, PD13);

论据乱七八糟,不正确。

有什么方法可以让我使用宏来传递一部分参数,而其他参数则正常传递?

【问题讨论】:

  • 我们应该看到所有的宏...
  • 如果你还没有这样做的话,你应该首先使用gcc -E 在宏扩展之后查看你的程序。
  • 在第一种形式中,initPin() 得到两个参数,在第二种形式中得到三个。 initPin() 的原型是什么?
  • 你有什么理由这样混淆你的代码?
  • 请更具体地说明您遇到的问题,并包括 GPIOD 的定义。预处理器应该可以按照您的使用方式正常工作,尽管人类读者可能会感到困惑。

标签: c macros concatenation c-preprocessor


【解决方案1】:

有什么方法可以让我使用宏来传递一部分 参数而其他参数正常传递?

没有。宏扩展完全是文本的,没有抑制所选参数扩展的机制。

但是,您可以定义不同的宏来实现类似的效果:

#define PD13_2args GPIOD, GPIO_Pin_13
#define PD13_1arg  GPIO_Pin_13
initPin(PD13_2args);
initPin(&p1, PD13_1arg);

您可能还想了解可变参数宏,这是 C99 及更高版本提供的一项功能,可与可变参数函数结合使用(例如 printf)。

【讨论】:

  • 我不想只使用宏中的一个参数。我想以与之前相同的方式使用宏,但修改函数以接受 3 个参数,第一个正常传递,另外 2 个由宏传递。
  • @PaulRox 第三个参数应该怎么办?您的意思是 initPin(x,y) 的两个参数版本在宏扩展后调用为 initPin(x,y,z) 时应该忽略第三个版本?很难说你想要什么。
  • 不不,最初我创建了 initPin 函数,就像我在帖子中写的第一个函数一样,带有 2 个参数并返回一个 PinType 变量,然后我想将 PinType 结构提供给作为参考传递的函数,所以我更改了函数的代码,如您在帖子中看到的那样。所以,问题在于该函数的第一个版本运行良好,而第二个版本由于使用宏传递的参数错误而无法运行。
  • @PaulRox 所以你已经重构了代码,以便 initPin() 有一个前置参数? “不起作用”到底是什么意思?有编译时错误吗?然后提供错误信息。是否存在运行时错误?然后提供一些信息。重构后是否重新编译了 all 文件?在显示的代码中,使用宏传递的参数不是“错误的”。有些事你没有告诉我们。
  • 现在开始工作了!无论如何,我仍然不明白问题出在哪里,我正在使用 Eclipse,并且我尝试在构建它之前制作“清洁项目”,现在它似乎按预期工作。在我尝试构建项目的所有其他时间,我检查了所有更改的文件是否已重新编译,所以我真的不明白为什么它应该在编译之前执行“清理项目”。
猜你喜欢
  • 2015-07-12
  • 1970-01-01
  • 2018-01-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多