如何在 C 中将联合指针作为参数传递? Union的内部是什么?
我有一个关于 c 中的 union 的问题。以下代码是服务器端,我们从客户端接收Signal2
,在服务函数中,我可以像这样检查信号类型:data_p->header.type
>?在 switch 情况下,我如何将参数传递给函数 printInfo(),它的参数是指向联合体的指针,如何传递?最后一个问题是指向联合体的指针,指向什么?联合体内部是什么,当分配这三个结构体时,它们如何适合联合体(具有大结构体的大小)?
union
{
Header header;
Signal1 signal1;
Signal2 signal2;
} Data;
struct Header
{
int type:
int protocol;
int clientId;
int serverId;
};
struct Signal1
{
int type:
int protocol;
int clientId;
int serverId;
char[80] something;
};
struct Signal2
{
int type:
int protocol;
int clientId;
int serverId;
int[100] something;
};
void service(Data* data_p) {
switch(data_p->header.type) {
case 1:
printInfo(&data_p->header);
case 2:
printInfo(data_p->header);
case 3:
data_p->signal2->something[5];
}
}
void printInfo(Data* data_p)
{
data_p->header.primitive;
}
I have a question about union in c. The following code is the server side, we receive Signal2
from the client side, in the service function, can I check the signal type like this: data_p->header.type
? and in the switch case, how could I pass the parameter to function printInfo(), the parameter of it is the pointer to the union, how to pass? And the last question is the pointer to the union, point to what? and what is inside of the union, when these three structs are allocated, how could they fit into the union(with the size of the large struct)?
union
{
Header header;
Signal1 signal1;
Signal2 signal2;
} Data;
struct Header
{
int type:
int protocol;
int clientId;
int serverId;
};
struct Signal1
{
int type:
int protocol;
int clientId;
int serverId;
char[80] something;
};
struct Signal2
{
int type:
int protocol;
int clientId;
int serverId;
int[100] something;
};
void service(Data* data_p) {
switch(data_p->header.type) {
case 1:
printInfo(&data_p->header);
case 2:
printInfo(data_p->header);
case 3:
data_p->signal2->something[5];
}
}
void printInfo(Data* data_p)
{
data_p->header.primitive;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
在您的示例中,您似乎希望依赖 Header、Signal1、Signal2 中的类型、协议、clientId、serverId 字段将以相同方式对齐这一事实。但 C 或 C++ 标准中没有任何内容可以保证这一点。所以它可能适用于大多数 C 编译器,但它是一种 hack,这种 hack 是不必要的。
看起来这样做会更好,如下所示:
至于你的最后一个问题,如果我理解正确的话,联合会为其最大的成员分配足够的内存,并在最严格的成员边界上对齐,并且在任何时间点都包含其成员之一的有效数据(但没有任何信息表明哪个是正确的)。指向 union 的指针是该内存区域的起始地址。
In your example it looks like you want to rely on the fact that the type, protocol, clientId, serverId fields from Header, Signal1, Signal2 will be aligned the same way. But nothing in the C or C++ standard guarantees that AFAIK. So it would probably work with most C compilers but it is a hack, where such a hack is not necessary.
It seems like it would be better to do things as follows :
As for your last question if I understand it correctly, the union is allocated enough memory for the largest of it's members, and aligned at the strictest of it's members' boundaries, and at any point in time contains valid data for one of it's members (but nothing indicating which is the correct one). And the pointer to union is the address of the start of that memory area.
我认为你的联合声明是没有按预期工作的部分。
尝试以下操作。
这应该创建一个名为
Data
的联合类型,而不是匿名联合类型的单个变量。从这里,即使通过
data_p->header.Type
传递Signal2
对象,您也应该能够访问Header
。I think your declaration of the union is the part that isn't working as expected.
Try the following.
This should make a union type called
Data
instead of a single variable of an anonymous union type.From here you should be able access the
Header
even when passed aSignal2
object viadata_p->header.Type
.类似的东西
可能是将指针传递给联合所持有的内容的好方法。
或者处理联合的函数的另一个参数,或者全局变量,或者配置参数。据我所知,工会的主张必须明确告知。
Something like
could be a good way of passing the pointer to what the union holds.
Or another argument to the function that processes the union, or a global variable, or a configuration parameter. As far as I know, what a union holds has to be explicitly told.
我认为联合中的头结构意味着变量的公共前缀。所以你可以像这样检查这个联合的类型:
所以是的,你可以用 data_p->header.type 检查。在我看来,你可以稍微重写一下代码,让它更明显,
我在
printInfo
标头中注意到的另一件事没有一个名为 Primitive 的变量从 switch 语句中,您可以使用
printInfo(data_p)
来正确调用它。这里最重要的是,程序员必须确保类型变量始终设置为正确的值,对应于联合部分的正确结构。
即,如果结构是 signal1,则为 1,如果是 signal2,则为 2,依此类推。
但是,联合的使用在这里毫无用处,因为除了最后一个字段之外,所有字段都是相同的,并且标头显然意味着访问公共字段。
}
I think the header structure in the union is meant to be the common prefix of variables. so you would check the type of this union like this:
So yes you can check with data_p->header.type. it seems to me that you could rewrite the code a little to get it more obvious
the other thing i notices in
printInfo
header doesn't have a variable called primitivefrom the switch statement you would call use
printInfo(data_p)
to call it correctly.The most important thing here is that the programmer has to make sure that the type variable is always set to the correct value, corresponding to the right struct of the union part.
i.e. if the struct is a signal1 its 1 and if it is a signal2 its 2 and so on
But the use of the union is quite useless here, since all fields are identical except the last one and the header is obviously meant to access the common fields.
}
访问联合成员的语法与访问结构成员的语法非常相似。一个使用 .运算符通过普通联合和 -> 访问联合字段通过指向联合的指针访问联合字段。假设您的示例中的数据联合:
至于 printinfo 的参数,代码中显示的参数类型是正确的,它应该是指向 Data 的指针。但是,正如其他地方所指出的, printInfo 中的代码不正确。我希望它在标头类型字段上包含一个类似于服务方法中的开关,如下所示:
正如其他地方所说,联合一次仅包含其成员之一。编译器为其提供了足够的空间来包含尽可能大的成员。将一种可能的数据类型存储在联合中会将数据覆盖在之前存在的数据上。
程序员必须跟踪哪些可能的元素已放入联合中,并适当地访问它。在示例中的数据联合中, header.type 字段用于此目的。
The syntax of accessing union members is very similar to that used to access structure members. One uses the . operator to access a union field through a plain union and the -> to access a union field through a pointer to union. Assuming the Data union in your example:
As to the parameter to printinfo, the parameter type shown in your code is correct, it should be a pointer to Data. However, the code inside printInfo is not correct, as pointed out elsewhere. I would expect it to contain a switch on the header type field similar to the one in the service method, as in the following:
As has also been said elsewhere, a union only contains one of its members at a time. The compiler gives it enough space to contain the largest possible member. Storing one of the possible data types in a union overlays the data on whatever was there before.
The programmer must keep track of which of the possible elements has been put into a union, and access it appropriately. In the Data union in your example, the header.type field is used for this purpose.
你需要
像这样 专门化 printinfo()
void printinfo(Header*)
void printinfo(Signal1*)
void printinfo(Signal2*)
然后像这样传递它
案例2:
printInfo(&data_p->signal1); // 将正确的联合成员传递给正确的函数,
因此实际上您没有传递联合,而是传递联合内的数据。
第二个问题:联合不是结构。工会
具有最大成员的大小。
你应该阅读sizeof a union in C/C++
祝你好运
you need to specialize printinfo()
like
void printinfo(Header*)
void printinfo(Signal1*)
void printinfo(Signal2*)
then pass it like
case 2:
printInfo(&data_p->signal1); // pass the right union member to the right function
so really you are not passing the union, you are passing the data inside the union.
second question: Unions are not structs. unions
have the size of the largest member.
you shoudl read sizeof a union in C/C++
good luck