2013-10-10 143 views
1

说,如果我有两个结构类型:我该如何做这样的结构类型转换?

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]的内容T的值,就像这样:

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; 
} 

回答

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语言不允许结构之间转换。

+0

C++确实允许在结构之间进行转换,但是您必须定义一个函数来指定转换完成的方式。没有默认行为。 –

0

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

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

我想如果'AArray [0]'是一个'lvalue',但好像初始化列表里面不能有'lvalues'。 – shengy

+1

@shengy基本上你要做的是'struct foo a = struct bar b'。那么,你不能直接或通过指针。 –

1

那么,你可以使用union

union UNION_AB { 
    TYPEA a; 
    TYPEB b; 
}; 

UNION_AB* UARRAY[1] = { &ua }; 
+1

如果你只访问第一个字段('UARRAY [0] - > aa'或等价地'UARRAY [0] - > ba'),这将工作,因为如果这些结构体具有兼容成员,但是一旦你越过这些,就进入了Undefined Behavior land。 –

+0

不仅如此;如果代码始终访问当时联合中的结构,则它是已定义的行为。 –