gpt4 book ai didi

c - 对我来说新的预处理器技巧

转载 作者:行者123 更新时间:2023-12-05 08:50:14 28 4
gpt4 key购买 nike

(以下代码是正确的,不是我自己创造的。)(它在电机板的配置中。)

#define BTN_TABLE(X) X(BUTTON, PA1)

#define BTN_X_EXTERNS(A, B) extern Button A;
BTN_TABLE(BTN_X_EXTERNS)

#define BTN_X_ID(A, B) A##_ID
#define BTN_X_ENUM(A, B) BTN_X_ID(A, B),
typedef enum { BTN_TABLE(BTN_X_ENUM) NUM_BOARD_BUTTONS } BoardButtonID;

#define BTN_X_FROM_ENUM(A, B) else if (button_id == BTN_X_ID(A, B)) return &A;
static __forceinline Button* button_from_enum(BoardButtonID button_id) {
if (0) return 0;
BTN_TABLE(BTN_X_FROM_ENUM)
else return 0;
}
  1. 我不明白 if (0) return 0; and else return 0; 的意思在上面的例子中。
  2. 为什么将 Marco 放在这两条线之间?
  3. 我认为我们不能在 if{} 和 else{} 语句之间放置任何内容。

最佳答案

我认为这段代码背后的意图如下:

  • 我们有一些按钮;目前只有一个,但最终可能会有更多

  • 每个按钮都需要一个相应的全局变量和 BoardButtonID 枚举中的一个值

  • 我们想要一个函数,它给定 enum BoardButtonID 值返回指向按钮全局变量的指针

  • 我们希望在只列出所有按钮一次的同时实现所有这些。

@bolov 展示了代码是如何展开的。我会注意到,只需更改 BTN_TABLE 宏的定义即可添加更多按钮:

#define BTN_TABLE(X) X(BUTTON, PA1) \
X(ANOTHER_BUTTON, PA2) \
X(YET_ANOTHER_BUTTON, PA3) \
X(OH_GOD_NOT_ANOTHER_BUTTON_MAKE_THEM_STOP, PA4)

PA1, PA2, ... 实际上并没有在这个版本的代码中使用;也许它们以后会被用于某些事情。

现在您可以 see效果(我重新格式化了输出):

extern Button BUTTON;
extern Button ANOTHER_BUTTON;
extern Button YET_ANOTHER_BUTTON;
extern Button OH_GOD_NOT_ANOTHER_BUTTON_MAKE_THEM_STOP;

typedef enum {
BUTTON_ID,
ANOTHER_BUTTON_ID,
YET_ANOTHER_BUTTON_ID,
OH_GOD_NOT_ANOTHER_BUTTON_MAKE_THEM_STOP_ID,
NUM_BOARD_BUTTONS
} BoardButtonID;

static __forceinline Button* button_from_enum(BoardButtonID button_id) {
if (0)
return 0;
else if (button_id == BUTTON_ID)
return &BUTTON;
else if (button_id == ANOTHER_BUTTON_ID)
return &ANOTHER_BUTTON;
else if (button_id == YET_ANOTHER_BUTTON_ID)
return &YET_ANOTHER_BUTTON;
else if (button_id == OH_GOD_NOT_ANOTHER_BUTTON_MAKE_THEM_STOP_ID)
return &OH_GOD_NOT_ANOTHER_BUTTON_MAKE_THEM_STOP;
else
return 0;
}

这清楚地说明了为什么需要初始 if:button_from_enum 中的宏扩展无法特殊处理第一个。因此它必须为每个按钮(包括第一个按钮)生成一个 else if,并且使该按钮有效的唯一方法是在开头有一个 if。它需要有一个总是失败的测试,因此 0,它对应的“then”子句无关紧要,因为它永远不会执行。那里的 return 0 可能刚刚被选择关闭关于函数可能返回没有值的编译器警告。当然,最后的 else 子句中的 return 0 是可以达到的,如果有人传递了一个与任何按钮都不匹配的值,它会作为默认值。

你是对的,如果你在 ifelse 之间放置任何其他内容,一切都会崩溃。

他们本可以稍微不同地定义它并使用 switch 来代替,这样会稍微干净一些。我不知道他们为什么不这样做;也许编译器生成了他们不喜欢的不同代码(例如,占用更多代码空间的跳转表)。

无论如何,生成的宏集虽然很聪明,但肯定不是很容易维护。他们可能应该考虑编写一个脚本,而不是从文本文件中的简单按钮列表生成所需的代码。

或者,他们可以将 Button 对象放在一个数组中,而不是坚持每个对象都有自己的变量。这与他们的 enum 很相配:

typedef enum { 
BUTTON_ID,
ANOTHER_BUTTON_ID,
YET_ANOTHER_BUTTON_ID,
OH_GOD_NOT_ANOTHER_BUTTON_MAKE_THEM_STOP_ID,
NUM_BOARD_BUTTONS
} BoardButtonID;

Button all_the_buttons[NUM_BOARD_BUTTONS];

static __forceinline Button* button_from_enum(BoardButtonID button_id) {
if (button_id < NUM_BOARD_BUTTONS)
return &all_the_buttons[button_id];
else
return NULL;
}

这种方式仍然只需要列出一次按钮,并且根本不涉及宏。

关于c - 对我来说新的预处理器技巧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62458254/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com