在C中的一个联合中存储不同的函数返回类型

时间:2017-10-20 21:15:49

标签: c unions

我在用言语制定目标时遇到了麻烦,所以我不太清楚如何表达这一点。

假设我有两个具有以下签名的功能:

myBigStruct_t function1()
int function2()

定义myBigStruct_t(存储大量数据并在其他地方)和一个可以支持两种返回类型大小的联合定义:

typedef union myUnion{
   myBigStruct_t A;
   int B;
} myData_t;

union my2ndUnion{
   myData_t data_;
   char myArray[sizeOf(myData_t)];
} un2;

我可以执行以下操作:

un2.myArray = function1();
...
if( something ){
   myExpress = un2.data_.A; 
else{
   myOtherExpress = un2.data_.B;
}
...
un2.myArray = function2();
if( something ){
   myExpress = un2.data_.A; 
else{
   myOtherExpress = un2.data_.B;
}

我知道数组数据通常是通过引用传递的,但是大多数C编译器都有一种传递大数据类型的方法,这些数据类型至少看起来是按值的(无论是否使用了秘密指针)。

我知道它有点做作;我只是想在工会中取得领先。

1 个答案:

答案 0 :(得分:0)

是的,这正是工会所做的。我认为这可以回答你的问题(如果没有,请告诉我),但我会给出更多背景信息。

如果myBigStruct_t定义如下:

typedef struct {
    char someChars[256];
    int  someInts[512];
} myBigStruct_t;

然后,当您从function1()进行分配时,将复制数据。没有秘密指针。

另一方面,如果myBigStruct_t定义如下:

typedef struct {
    char *someChars; //This gets malloc'd in function1
    int  *someInts; //This gets malloc'd in function1
} myBigStruct_t;

然后数据通过引用传递,即数据未被复制。

请注意,由于function1myArray的返回值之间的类型不匹配,您的代码将无法正常工作,function2的返回值也相同。您必须分配特定的工会成员:

un2.myArray.data_.A = function1();
un2.myArray.data_.B = function2();

我认为没有任何理由不这样做。

编辑(回复您的评论):

为什么不直接将数组作为参数传递而不是返回值?函数原型就像:void foo(void* buffer, size_t buffer_len)。我假设你完全理解指针(否则函数指针可能不是解决问题的正确方法)。完整的程序可能如下所示:

//All the functions use this prototype, although it isn't strictly necessary (your loop would just have to be smarter)
typedef void(*GenericFunctionCall)(void* buffer, size_t buffer_len);

//A struct with only a few bytes
typedef struct SmallStruct_s{
    char value;
} SmallStruct_t;

//A struct with more bytes
typedef struct BigStruct_s {
    char value[1024];
} BigStruct_t;

//Defining this makes it easy to get the maximum size of all the structs
typedef union AllStructs_s {
    SmallStruct_t small;
    BigStruct_t big;
} AllStructs_t;

//This function takes the buffer, casts it to a SmallStruct_t, and then does something with it (presumably sets param->value to something)
void smallFunction(void* buffer, size_t buffer_len) {
    SmallStruct_t * param = (SmallStruct_t*)buffer;

    //do something with param
}
    //This function does the same with BigStruct_t
void bigFunction(void* buffer, size_t buffer_len) {
    BigStruct_t * param = (BigStruct_t*)buffer;

    //do something with param
}



int main() {
    //This allocates memory for all the values generated by smallFunction and bigFunction.
    AllStructs_t param;

    //This is your table of function pointers
    GenericFunctionCall functions[2];
    functions[0] = smallFunction;
    functions[1] = bigFunction;

    //Loop through the functions and do something with the results
    for (uint32_t function_index = 0; function_index < 2; ++function_index) {
        functions[function_index]((void*)&param, sizeof(AllStructs_t));

        //Do something with param here
    }
}

第二次编辑:

好的,我现在看到你正在尝试做什么。你不能使用union之间接受任意值,在这种情况下,unions与任何其他数据类型没有区别(即我不能分配BigStruct_t = SmallStruct_t)。

原因如下:当编译器生成代码来处理函数的返回值时,它使用调用者的内存来存储值。因此,您不能获得指向函数返回值的指针。在compiler-speak中:函数的返回值不是lvalue。解决这个问题的选择是:

  • 将函数的返回类型存储在表中,并使用该函数分配相应的变量
  • 从表中为每个函数编写一个包装函数,并将返回类型从返回值转换为指针参数。调用包装器而不是原始函数
  • 完全重构代码