2013-10-10 92 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

不僅如此;如果代碼始終訪問當時聯合中的結構,則它是已定義的行爲。 –