Amb*_*wal 9 c arrays switch-statement
我有一些常量值和数组定义他们的标签和他们的哈希码.例如,
#define LABEL_A 0 //or const int LABEL_A = 0;
#define LABEL_B 1
#define LABEL_C 2
#define LABEL_D 3
const char *VALUE[] = {"LABEL_A", "LABEL_B", "LABEL_C", "LABEL_D"};
const int VALUE_HASH[] = {67490, 67491, 67493, 67459);
Run Code Online (Sandbox Code Playgroud)
在运行时,这些标签可以按任何顺序排列,需要进行相应的解析.我正在使用开关盒来达到这个目的.此代码在编译时生成错误"需要常量表达式.
function(const char* LabelAtRuntime){
int i = getHashCode(LabelAtRuntime);
switch(i){
case VALUE_HASH[LABEL_A]: //line giving compile time error
break;
default:
break;
}
Run Code Online (Sandbox Code Playgroud)
但是,当我提供实际常量时,它是有效的.这段代码效果很好.
function(const char* LabelAtRuntime){
int i = getHashCode(LabelAtRuntime);
switch(i){
case 67490: //line not giving compile time error
break;
default:
break;
}
Run Code Online (Sandbox Code Playgroud)
我以这种方式使用常量来提供更好的代码语义,可读性和可重用性.请不要提供if-else基础解决方案.在上面的例子中,只有4个标签,但实际上可能有100个.
PSk*_*cik 11
在C++中,这编译:
#include <stdio.h>
#include <stdlib.h>
constexpr int x[] = { 42, 43 };
int main(int argc, char **argv)
{
switch(atoi(argv[1]))
{
case x[0]: puts("forty_two");
break;
case x[1]: puts("forty_three");
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
因此constexpr在阵列上似乎是现代C++中的解决方案.(注意:问题最初标记为C++和C)
如果你想保留阵列,那么在C中是不可能的.切换情况需要一个整数常量,但是一旦在变量中放入一个整数常量,它就会变成一个运行时实体(即使它被声明为const).你可以做的是用一堆直接定义替换内存中的数组,并且可能有一个使用其他宏查找宏的宏(如果你想保留你的代码形式):
#define LABEL_A 0
#define LABEL_B 1
#define LABEL_C 2
#define LABEL_D 2
#define VALUE_HASH__0 67490
#define VALUE_HASH__2 67491
#define VALUE_HASH__3 67491
#define VALUE_HASH__4 64759
//append what Index expands to to VALUE_HASH__
#define HASH_LOOKUP(Index) MC_cat(VALUE_HASH__,Index)
#define MC_cat_(X,Y) X##Y
#define MC_cat(X,Y) MC_cat_(X,Y)
function(const char* LabelAtRuntime){
int i = getHashCode(LabelAtRuntime);
switch(i){
case HASH_LOOKUP(LABEL_A)
break;
default:
break;
}
Run Code Online (Sandbox Code Playgroud)
出错的原因很简单,C不认为const int LABEL_A=0;是编译时常量.不幸的是,语言是如何定义的.它可以通过#define LABEL_A 0改为使用来解决.
第三种方法是使用枚举,这可能更好,因为它们可用于将所有数据绑定在一起,并在维护期间提供更多的数据完整性:
typedef enum
{
LABEL_A,
LABEL_B,
LABEL_C,
LABEL_D,
LABELS_N
} label_index_t;
typedef void func_t (void);
typedef struct
{
const char* str;
int hash;
func_t* func;
} value_t;
...
const value_t VALUE [] =
{
[LABEL_A] = { .str = "LABEL_A", .hash = 67490, .func = a_func },
[LABEL_B] = { .str = "LABEL_B", .hash = 67491, .func = b_func },
[LABEL_C] = { .str = "LABEL_C", .hash = 67493, .func = c_func },
[LABEL_D] = { .str = "LABEL_D", .hash = 67459, .func = d_func },
};
_Static_assert(sizeof VALUE / sizeof *VALUE == LABELS_N,
"Size of VALUE does not match label_t.");
...
// instead of switch(n):
VALUE[n].func();
Run Code Online (Sandbox Code Playgroud)