我正在编写一个C程序,我在其中定义了两种类型:
typedef struct {
uint8_t array[32];
/* struct A's members */
...
} A;
typedef struct {
uint8_t array[32];
/* struct B's members, different from A's */
...
} B;
现在我想建立一个能够管理这两种类型的数据结构,而不必为类型A写一个,假设两个都有一个uint8_t [32]作为它们的第一个成员。
我读了如何在C here中实现一种多态,我还读到here结构成员的顺序保证由程序员编写的编译器保留。
我提出了以下想法,如果我定义以下结构怎么办:
typedef struct {
uint8_t array[32];
} Element;
并定义一个仅处理具有Element类型的数据的数据结构?做类似的事情是否安全:
void f(Element * e){
int i;
for(i = 0; i < 32; i++) do_something(e->array[i]);
}
...
A a;
B b;
...
f(((Element *)&a));
...
f(((Element *)&b));
乍一看它看起来不干净,但我想知道是否有任何保证不会破坏?
答案 0 :(得分:1)
如果array
始终是结构中的第一个,则只需通过转换指针即可访问它。不需要结构Element
。您的数据结构可以存储void指针。
typedef struct {
char array[32];
} A;
typedef struct {
void* elements;
size_t elementSize;
size_t num;
} Vector;
char* getArrayPtr(Vector* v, int i) {
return (char*)(v->elements) + v->elementSize*i;
}
int main()
{
A* pa = malloc(10*sizeof(A));
pa[3].array[0] = 's';
Vector v;
v.elements = pa;
v.num = 10;
v.elementSize = sizeof(A);
printf("%s\n", getArrayPtr(&v, 3));
}
答案 1 :(得分:0)
但为什么没有直接使用数组的函数
void f(uint8_t array[32]){
int i;
for(i = 0; i < 32; i++) do_something(array[i]);
}
并像这样称呼它
f(a.array)
f(b.array)
多态性是有意义的 a和b在某种容器中 并且你想迭代它们,但你不想关心它们是不同的类型。
答案 2 :(得分:0)
如果您不犯任何错误,这应该可以正常工作。指向A
结构的指针可以转换为指向element
结构的指针,只要它们具有公共前缀,对公共成员的访问就可以正常工作。
指向A
结构的指针,然后转换为指向element
结构的指针,也可以转换回指向A
结构的指针,没有任何问题。如果element
struct最初不是A
结构,那么将指针强制转换回A
将是未定义的行为。这需要您手动管理。
一个问题(我遇到过)是,gcc还允许你来回转换struct
(不只是指向结构的指针),这是不受支持的按C标准。它似乎工作正常,直到你(我的)朋友试图将代码移植到另一个编译器(suncc),此时它将破坏。或者更确切地说,它甚至不会编译。