Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.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_Arrays - Fatal编程技术网

';类型安全';枚举以避免在C中检查数组索引

';类型安全';枚举以避免在C中检查数组索引,c,arrays,C,Arrays,使用“类型安全”枚举限制函数的参数是否合适,以避免检查数组索引是否超出范围 我有一个模块,它将其实例的数据保存在一个数组中。实例的数据应该通过索引从模块外部访问。将有几个接口函数,我希望避免使用几个if语句 以下示例: // In myInstanceModule.h typedef struct { enum { FIRST, SECOND } index_e; } instance_tst; #define FIRST_INSTANCE (instance_tst){ FIRST } #

使用“类型安全”枚举限制函数的参数是否合适,以避免检查数组索引是否超出范围

我有一个模块,它将其实例的数据保存在一个数组中。实例的数据应该通过索引从模块外部访问。将有几个接口函数,我希望避免使用几个if语句

以下示例:

// In myInstanceModule.h

typedef struct { enum { FIRST, SECOND } index_e; } instance_tst;
#define FIRST_INSTANCE  (instance_tst){ FIRST }
#define SECOND_INSTANCE (instance_tst){ SECOND }

void instance_init_v();
void instance_print_v(instance_tst instance);

// In myInstanceModule.c

#define MEMBER_COUNT 2

typedef struct myArray {
    int myValue; 
}myArray_tst;

static myArray_tst myMembers_ast[MEMBER_COUNT];

void instance_init_v() {
    for (int i = 0; i < MEMBER_COUNT; i++)
    {
        myMembers_ast[i].myValue = i * 10;
    }
}

void instance_print_v(instance_tst instance) {
    printf("Value of this instance is: %d \n", myMembers_ast[instance.index_e].myValue);
}

// In main.c

#include myModule.h
int main(void)
{
    int test = 1234;
    instance_init_v();

    instance_print_v(FIRST_INSTANCE);       // ok
    instance_print_v(SECOND_INSTANCE);      // ok
    //instance_print_v((instance_tst)2);    // does not compile
    //instance_print_v(test);               // does not compile
    //instance_print_v(1);                  // does not compile
    //instance_print_v(NULL);               // does not compile
}
//在myInstanceModule.h中
typedef结构{enum{FIRST,SECOND}索引}实例};
#定义第一个实例(实例_tst){FIRST}
#定义第二个_实例(实例_tst){SECOND}
void instance_init_v();
作废实例打印(实例打印实例);
//在myInstanceModule.c中
#定义成员计数2
类型定义结构myArray{
int-myValue;
}myArray_tst;
静态myArray_tst myMembers_ast[成员计数];
void instance_init_v(){
对于(int i=0;i

一个文件中的示例:

不幸的是,C对枚举非常宽容。枚举只是符号常量的列表,您可以通过使用基础类型来欺骗它。这里

instance_print_v((instance_tst){2});    // does compile

编译没有问题(甚至没有警告),并导致访问超过您试图阻止的数组的末尾。

这种方法不会阻止某人使用复合文本,例如

instance_print_v(((instance_tst){2}));
我宁愿这样做

void instance_print_v(size_t index){
    if(index < sizeof(myMembers_ast)/sizeof(myMembers_ast[0]))
    {
      printf("Value of this instance is: %d \n", myMembers_ast[index].myValue);
    }
    else
    {
      printf("Value of this instance is: undefined");
    }
}
void实例打印(大小索引){
if(索引
根据我在这里发明的技巧调整您的代码:,然后我会得到如下结果:

#include <stdio.h>

// In myInstanceModule.h

typedef enum
{
  FIRST,
  SECOND
} instance_tst;

typedef union
{
  instance_tst FIRST;
  instance_tst SECOND;
} typesafe_instance_t;

#define instance_assign(var, val) _Generic((var), \
  instance_tst: (var) = (typesafe_instance_t){ .val = val }.val )

void instance_init_v();
void instance_print (instance_tst instance); // the actual function

// type-safe wrapper:
#define instance_print_v(val) instance_print( instance_assign((instance_tst){0}, val) )

// In myInstanceModule.c

#define MEMBER_COUNT 2

typedef struct myArray {
    int myValue; 
}myArray_tst;

static myArray_tst myMembers_ast[MEMBER_COUNT];

void instance_init_v() {
    for (int i = 0; i < MEMBER_COUNT; i++)
    {
        myMembers_ast[i].myValue = i * 10;
    }
}

void instance_print (instance_tst instance) {
    printf("Value of this instance is: %d \n", myMembers_ast[instance].myValue);
}

// In main.c

int main(void)
{
    int test = 1234;
    instance_init_v();

    instance_print_v(FIRST);       // ok
    instance_print_v(SECOND);      // ok

    //instance_print_v((instance_tst)2);    // does not compile
    //instance_print_v(test);               // does not compile
    //instance_print_v(1);                  // does not compile
    //instance_print_v(NULL);               // does not compile
    //instance_print_v((instance_tst){20}); // does not compile
}
#包括
//在myInstanceModule.h中
类型定义枚举
{
第一,
第二
}实例(t);
typedef联合
{
先例;
实例二;
}类型安全实例;
#定义实例分配(var,val)通用((var)\
实例_tst:(var)=(typesafe_实例_t{.val=val}.val)
void instance_init_v();
无效实例_打印(实例_tst实例);//实际功能
//类型安全包装器:
#定义实例_print_v(val)实例_print(实例_赋值((实例_tst){0},val))
//在myInstanceModule.c中
#定义成员计数2
类型定义结构myArray{
int-myValue;
}myArray_tst;
静态myArray_tst myMembers_ast[成员计数];
void instance_init_v(){
对于(int i=0;i

不幸的是,这也会阻止
instance\u tst
变量传递到函数,但据我所知,这不是问题。

您错过了最明显的滥用方式:try
instance\u print\v((instance\u tst){20})哦,对了。非常感谢你。你有没有办法摆脱它?没有,除了使用范围检查之外,我没有别的解决办法。但这正是你想要避免的(相关:。在我所看到的由于数组边界而导致的所有崩溃和内存损坏之后,我建议您始终检查它们。给自己一个更轻松的生活。免责声明:积分应该转到@Gerhardh,他在我测试时在评论中回答了这一问题…公平地说,像这样的简单边界检查可能是最好的解决方案。其他解决方案ns可能看起来很优雅,但它们增加了很多复杂性。