【问题标题】:How can I do a structure type conversion like this?我怎样才能进行这样的结构类型转换?
【发布时间】:2013-10-17 15:48:51
【问题描述】:

如果我有两种结构类型:

typedef struct
{
   unsigned int * a;
   char * b;
   char * c;
}TYPEA;

typedef struct
{
   unsigned int * a;
   unsigned int * b;
}TYPEB;

我还有一个指针数组,其中包含指向TYPEA类型的指针:

TYPEA* AArray[1] =
{
   &ga,
};

ga 定义为:

TYPEA ga =
{
   &num1,
   &b,
   &c,
};

如果我定义了另一个TYPEA var,我可以修改AArray[0] 的内容值,如下所示:

TYPEA another_ga =
{
   &num3,
   &b,
   &c,
};

void change_AArray()
{
   *AArray[0] = another_ga;
}

这很好用,但问题是,TYPEATYPEB 的前 32 位相同(两者都是 unsigned int)我是否可以更改 AArrayga' s 内容到TYPEB 结构?

这是我的尝试:

void change_AArray()
{
   /* *AArray[0] = another_ga; */

   /* Compile Error */
   /* *AArray[0] = gb; */

   /* Compile Error */
   /* *AArray[0] = (TYPEA)gb; */

   /* Passed compile, but AArray[0] is not changed */
   /* AArray[0] = (TYPEA*)&gb; */
}

然后我尝试添加另一个指针并将其放入AArray[0]而不是使用&ga,但它无法通过编译阶段,我认为C在初始化列表中需要一个常量。

TYPEA * pga = &ga;
TYPEA* AArray[1] =
{
   pga, // error, needs a constant expression.
};
void change_AArray()
{
   AArray[0] = (TYPEA*)&gb;
}

是否可以进行类型转换?

整个代码:

#include <stdio.h>

typedef struct
{
   unsigned int * a;
   char * b;
   char * c;
}TYPEA;

typedef struct
{
   unsigned int * a;
   unsigned int * b;
}TYPEB;

int num1 = 10, num2 = 20, num3 = 30;
char b = 'b', c = 'c';

TYPEA ga =
{
   &num1,
   &b,
   &c,
};

TYPEA another_ga =
{
   &num3,
   &b,
   &c,
};

TYPEB gb =
{
   &num2,
   &num3,
};

TYPEA* AArray[1] =
{
   &ga,
};

void change_AArray()
{
   *AArray[0] = another_ga;
   /* How can I do this conversion? */
   /* *AArray[0] = gb; */
}

int main(int argc, const char *argv[])
{
   printf("ga.a: %d\n", *ga.a);
   printf("gb.b: %d\n", *gb.a);

   change_AArray();

   printf("After calling change_AArray()\n");
   printf("ga.a: %d\n", *ga.a);
   printf("gb.b: %d\n", *gb.a);

   return 0;
}

【问题讨论】:

    标签: c pointers struct type-conversion


    【解决方案1】:
    void change_AArray()
    {   
       *AArray[0] = *((TYPEA*) &gb);  //#1
       /* error:
       *(AArray[0]) = (TYPEA) gb;     //#2
       */
    }
    

    您可以将 #1 用于您的目的。

    如果使用#2,gcc会报错:
    错误:请求转换为非标量类型

    问题是:
    - 什么是标量/非标量类型?
    - 这个错误信息是什么意思?
    - 为什么#2 失败了?

    什么是标量/非标量类型?
    int、char、指针是标量类型,结构不是。
    在此处查看详细信息,http://herbert.the-little-red-haired-girl.org/en/prgmsc1/docs/part2a.pdf

    这个错误信息是什么意思?
    如果你在标量和非标量类型之间进行赋值,你会得到这个错误。

    为什么#2 失败了?
    对于*(AArray[0]) = (TYPEA) gb;,两边都是非标量类型。因此,它看起来不应该出现上述错误。
    但是,C 不允许在结构之间进行强制转换。见http://msdn.microsoft.com/en-us/library/d9f2bsy2.aspx

    一个测试程序,

    struct a{ int i;};
    struct b{ int i; };
    
    int main (int argc, char *argv[])
    {
        struct a aaa;
        struct b bbb;
        bbb = (struct b)aaa;
    
        return 0;
    }
    

    gcc 报错: error: conversion to non-scalar type requested

    总而言之,#2 失败的原因是 C 语言不允许结构之间的转换。

    【讨论】:

    • C++ 确实允许在结构之间进行转换,但您必须定义一个函数来指定如何进行转换。没有默认行为。
    【解决方案2】:

    嗯,你可以使用联合

    union UNION_AB {
      TYPEA a;
      TYPEB b;
    };
    
    UNION_AB* UARRAY[1] = { &ua };
    

    【讨论】:

    • 如果您只访问第一个字段(UARRAY[0]-&gt;a.a 或等效的UARRAY[0]-&gt;b.a),这将起作用,因为如果这些结构具有兼容的成员,则结构的联合确实具有定义的行为,但是一旦您过去那些,你进入未定义的行为领域。
    • 不仅如此;如果代码始终访问当时联合中的结构,则它是已定义的行为。
    【解决方案3】:

    你不能直接投射两种不同类型的struct,你必须像这样分配字段:

    (*AArray[0]).a = gb.a;
    

    【讨论】:

    • 如果AArray[0]lvalue,我想我可以,但似乎初始化列表里面不能有lvalues
    • @shengy 基本上你想要做的是struct foo a = struct bar b。好吧,你不能直接或通过指针来做到这一点。
    猜你喜欢
    • 2022-10-24
    • 2022-11-29
    • 2016-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-16
    • 1970-01-01
    相关资源
    最近更新 更多