我想在C中的结构中添加一个字段。例如,我有以下结构。
struct A
{
some_type x;
some_type y;
}
我声明了一个新的结构,就像这样。
struct B
{
A a;
some_type z;
}
现在说我有这样的功能。
int some_function( A * a )
是否可以在程序中将类型B的变量传递给它。
B * b;
......
A * a = (A*)b;
some_function( a );
还可以使用some_function
来使用a->x
中的字段吗?
答案 0 :(得分:9)
是的,它是有效的。标准的话,C99 6.7.2.1/13:
...指向a的指针 结构对象,适当转换,指向其初始成员(或者如果该成员是a 位字段,然后到它所在的单元,反之亦然。可能有未命名的 在结构对象中填充,但不在其开头。
答案 1 :(得分:1)
是的,它会起作用。 a将是struct
中的第一个成员这是一些人在C
中模拟OO继承的方式您可以使用
&b->a
而不是演员。 并且可能做一个像
这样的ASSERT ASSERT (&b->a == b)
当你意外地破坏了这个语义时会被警告
答案 2 :(得分:1)
为什么不在成员上调用方法?
some_function( &b->a );
您的代码现在可以使用了,但是如果有人决定更改B
的成员呢?或者在a
之前添加新成员?
答案 3 :(得分:0)
不,它不会起作用。如果你稍微改变它将工作:
struct A
{
some_type x;
some_type y;
}; /* <- note semicolon here */
struct B
{
struct A a;
some_type z;
}; /* ... and here */
int some_function(struct A *a ); /* ... and here ... */
struct B *b;
......
struct A *a = (struct A*)b;
some_function( a );
答案 4 :(得分:0)
是的,这可行,但只是偶然。
如果我正确地回忆起C99标准,那么这个特殊情况需要按预期工作。但很明显,这只是因为在此之前有足够多的人依赖它工作,并且它在很多实施中偶然发挥作用,C99标准委员会认为有必要立法在法律上和事实上进行立法。 / p>
不要让那诱惑你认为这是个好主意。
任何依赖于标准边缘情况的东西都会在破碎的边缘永久地摇摇欲坠,因为它看起来很丑陋(因此使你的代码的未来读者感到不舒服)并且看起来很聪明(这使得他们对改变/修复任何东西感到紧张)。此外,它引导民众做出假设,因为你已经处于合法的边缘,可以诱使跨越国界的民众成为破碎的代码。例如,结构中第一个子结构中的第一个元素按预期对齐,这并不意味着任何其他子元素都排成一行。它适用于你的编译器这一事实并不意味着它对任何其他人都有效,导致令人费解的混乱错误。
写:
A *a = &(b->a);
(如上面的评论所示),你的意思很清楚。
如果由于某些不明原因你必须将B*
强制转换为A*
,那么请写一个非常明确的评论,解释为什么你别无选择,只能做你必须做的事情做,向读者保证它是合法的,并指向授权它的C99标准的子部分。
如果你真的找不到那个小节(并且发现它是你的作业/忏悔),那么就这样评论,我会把它挖出来。