我正在编写一个C程序,它根据环境变量对数组应用不同类型的量化.

问题是,我需要使用相同的函数void foo(void* ptr, quant_t type, ...)在PTR上执行操作,但我需要事先将其强制转换为正确的类型.

(quant_t是枚举类型对象)

我试着go 做

void foo(void* ptr, quant_t type, ...){
switch(type){
case UNIF:{
struct unif* my_ptr = (struct unif*) ptr;
break;
}
case KMEANS:{
struct kmeans* my_ptr = (struct kmeans*) ptr;
break;
}...}

my_ptr->a = bar(...);
my_ptr->b = baz(...);
}

但它不起作用,因为my_ptr的声明在切换用例的作用域内.

So 我试着go 做 something like this:

void foo(void* ptr, quant_t type, ...){
void* my_ptr = NULL;
switch(type){
case UNIF:{
my_ptr = (struct unif*) ptr;
break;
}
case KMEANS:{
my_ptr = (struct kmeans*) ptr;
break;
}...}

my_ptr->a = bar(...);
my_ptr->b = baz(...);
}

但还是不行.

推荐答案

要使->a正常工作,编译器必须知道字段相对于指针的位置(以及其他信息).此偏移量必须以C表示为常量.

我们可以通过使您的两个类型与第三个类型兼容并使用第三个类型(Base)来实现这一点.

typedef struct {
   A a;
   B b;
} Base;

typedef struct {
   Base base;
   …
} Unif;

typedef struct {
   Base base;
   …
} Kmeans;
// `base` doesn't need to be the first field of `Unif` and `Kmeans`
// (unless you want to recuperate the orig ptr from a `Base *` at some point).

void foo( Base *ptr, … ) {
   ptr->a = bar( … );
   ptr->b = baz( … );
}

Unif *unif = …;
foo( &unif->base, … );

Kmeans *kmeans = …;
foo( &kmeans->base, … );

它不那么安全,但我们也可以这样称呼它:

// `base` must be the first field of `Unif` and `Kmeans`.

void foo( Base *ptr, … ) {
   ptr->a = bar( … );
   ptr->b = baz( … );
}

Unif *unif = …;
foo( (Base *)unif, … );

Kmeans *kmeans = …;
foo( (Base *)kmeans, … );

这意味着我们可以进行一些更改,以减少调用方所需的代码.

// `base` must be the first field of `Unif` and `Kmeans`.

void foo( void *ptr_, … ) {
   Base *ptr = ptr_;
   ptr->a = bar( … );
   ptr->b = baz( … );
}

Unif *unif = …;
foo( unif, … );

Kmeans *kmeans = …;
foo( kmeans, … );

后两种方法不像原始方法那样安全,因为它们通过显式和隐式强制转换通过类型判断.

C++相关问答推荐

如何通过Zephyr(Devicetree)在PR Pico上设置UTE 1?

以c格式打印时间戳

不同到达时间的轮询实现

由Go调用E.C.引起的内存快速增长

在函数中使用复合文字来初始化C语言中的变量

为什么在4.9.37版的内核中,kfio还需要smp_wmb呢?

如何在IF语句中正确使用0.0

LibpCap禁用监视器模式(C、MacOS)

在我的代码中,我需要在哪里编写输出函数?

什么是.c.h文件?

用C语言计算文本文件中的整数个数

从C文件中删除注释

如何使用libgpio(d)为Raspberry Pi编译C程序?

使用Open62541向OPCUA服务器发送读请求时内存泄漏

如何使这个While循环在新行上结束

从不兼容的指针类型返回&&警告,但我看不出原因

如何打印循环调度问题的时间表

C程序printf在getchar while循环后不工作

If语句默认为true

GDB 跳过动态加载器代码