我可以使用预处理器使这个更清楚吗?
Could I use preprocessor to make this one clearer?
我正在为我的 Pic32 编写一个小的源文件函数,但我被困在一件事上。
它基本上是一个实用程序,应该将传入的 char
数据存储到缓冲区中,然后,如果收到 '\r'
,它将缓冲区与命令列表(在数组 names
中)进行比较,如果匹配找到,返回项目的索引。
这部分来自header:
#define NAMECNT 6
static const char names[NAMESCNT][10] = { // 6commands, max 10 char each
"korr", // 1
"adc", // 2
"fft", // 3
"data", // 4
"pr", // 5
"prsc"}; // 6
/* functions */
extern int comm(char cdata);
在主文件中,有一个大开关:
switch( comm(recieved_ch) ){
case 1: foo1(); break;
case 2: foo2(); break;
...
}
现在,为了更清楚起见,我想使用原始名称(如 case KORR: case ADC:
)而不是 1、2...,所以我为每个名称都写了定义
#define KORR 1
#define ADC 2
但我不喜欢这个解决方案,因为我想在更多项目中使用这个源文件,每个项目都有不同的命令列表。有什么办法吗?
最好的办法是在预处理器中创建数组名称,但我怀疑这是否可能。我正在考虑使用枚举类型(它与命令列表具有相同的项目names
),但我不确定那会怎样。
预处理器可以使这里的事情更清楚,我认为,使用连接运算符 ##
,但它不会产生性能优势。 switch
语句可以由编译器优化,但这取决于实现。
而不是 "one big switch," 使用函数指针数组。像
func_ptrs[comm(received_ch) - 1]();
会调用相应的函数,其中foo1
在索引0
,foo2
在1
等。要添加命令,只需附加命令名称到命令列表和函数指针 func_ptrs
.
毕竟,你用一块石头杀死了两只鸟:你创造了一种添加命令和提高性能的简单方法。
此外,通过字符串数组进行线性搜索效率非常低。哈希 table 会产生性能优势。
你可以使用X-macros建立一个enum
并填充数组,然后你可以使用switch
中的enum
值:
#define VARS \
X(korr) \
X(adc) \
X(fft) \
X(data) \
X(pr) \
X(prsc)
static const char names[][10] = { // 6commands, max 10 char each
#define X(name) #name,
VARS
#undef X
};
enum evars {
#define X(name) name,
VARS
#undef X
};
extern int comm(char cdata);
int main(void)
{
char x = 1;
switch (comm(x)) {
case korr:
printf("korr");
break;
case adc:
printf("adc");
break;
/* ... and so on */
}
return 0;
}
X
的展开为:
static const char names[][10] = {
"korr", "adc", "fft", "data", "pr", "prsc",
};
enum evars {
korr, adc, fft, data, pr, prsc,
};
编辑:正如@5gon12eder 所指出的,您不需要在数组的第一维中硬编码 6(您可以不指定)。
我正在为我的 Pic32 编写一个小的源文件函数,但我被困在一件事上。
它基本上是一个实用程序,应该将传入的 char
数据存储到缓冲区中,然后,如果收到 '\r'
,它将缓冲区与命令列表(在数组 names
中)进行比较,如果匹配找到,返回项目的索引。
这部分来自header:
#define NAMECNT 6
static const char names[NAMESCNT][10] = { // 6commands, max 10 char each
"korr", // 1
"adc", // 2
"fft", // 3
"data", // 4
"pr", // 5
"prsc"}; // 6
/* functions */
extern int comm(char cdata);
在主文件中,有一个大开关:
switch( comm(recieved_ch) ){
case 1: foo1(); break;
case 2: foo2(); break;
...
}
现在,为了更清楚起见,我想使用原始名称(如 case KORR: case ADC:
)而不是 1、2...,所以我为每个名称都写了定义
#define KORR 1
#define ADC 2
但我不喜欢这个解决方案,因为我想在更多项目中使用这个源文件,每个项目都有不同的命令列表。有什么办法吗?
最好的办法是在预处理器中创建数组名称,但我怀疑这是否可能。我正在考虑使用枚举类型(它与命令列表具有相同的项目names
),但我不确定那会怎样。
预处理器可以使这里的事情更清楚,我认为,使用连接运算符 ##
,但它不会产生性能优势。 switch
语句可以由编译器优化,但这取决于实现。
而不是 "one big switch," 使用函数指针数组。像
func_ptrs[comm(received_ch) - 1]();
会调用相应的函数,其中foo1
在索引0
,foo2
在1
等。要添加命令,只需附加命令名称到命令列表和函数指针 func_ptrs
.
毕竟,你用一块石头杀死了两只鸟:你创造了一种添加命令和提高性能的简单方法。
此外,通过字符串数组进行线性搜索效率非常低。哈希 table 会产生性能优势。
你可以使用X-macros建立一个enum
并填充数组,然后你可以使用switch
中的enum
值:
#define VARS \
X(korr) \
X(adc) \
X(fft) \
X(data) \
X(pr) \
X(prsc)
static const char names[][10] = { // 6commands, max 10 char each
#define X(name) #name,
VARS
#undef X
};
enum evars {
#define X(name) name,
VARS
#undef X
};
extern int comm(char cdata);
int main(void)
{
char x = 1;
switch (comm(x)) {
case korr:
printf("korr");
break;
case adc:
printf("adc");
break;
/* ... and so on */
}
return 0;
}
X
的展开为:
static const char names[][10] = {
"korr", "adc", "fft", "data", "pr", "prsc",
};
enum evars {
korr, adc, fft, data, pr, prsc,
};
编辑:正如@5gon12eder 所指出的,您不需要在数组的第一维中硬编码 6(您可以不指定)。