简体   繁体   English

类型转换结构指针

[英]Type casting struct pointer

I'm trying to get into Socket programming and came across an article at https://www.tenouk.com/Module43a.html I'm having difficulty understanding as how a char array is cast into struct pointer 我正在尝试进行Socket编程,并在https://www.tenouk.com/Module43a.html上遇到了一篇文章,由于将char数组如何转换为结构指针,我很难理解

char buffer[PCKT_LEN];
struct ipheader *ip = (struct ipheader *) buffer;
//some code here
ip->iph_ihl = 5;
ip->iph_ver = 4;
ip->iph_tos = 16;

As per my understanding, pointer ip will now hold the address of buffer and values for members of struct ipheader will now be stored in buffer. 根据我的理解,指针ip现在将保存缓冲区的地址,而struct ipheader成员的值现在将存储在缓冲区中。 Please help understanding the same. 请帮助理解相同的。 If I'm right, then how would we be able to print values stored in buffer? 如果我是对的,那我们将如何打印存储在缓冲区中的值?

You understanding is correct. 您的理解是正确的。 The pointer *ip will point to buffer. 指针* ip将指向缓冲区。 char buffer[PCKT_LEN] is an array of size sizeof(char) * PCKT_LEN. char buffer [PCKT_LEN]是一个大小为sizeof(char)* PCKT_LEN的数组。 Since a char is usually 1 byte long it is just a chunk of memory of PCKT_LEN bytes. 由于char通常为1个字节长,因此它只是PCKT_LEN个字节的内存块。 PCKT_LEN is defined to be 8192 PCKT_LEN定义为8192

The amount of bytes needed to store a struct ipheader is much less than this. 存储一个struct ipheader所需的字节数比这少得多。 Try int a = sizeof(ipheader) and use a debugger to see the value assigned to a . 尝试int a = sizeof(ipheader)和使用调试器看分配给值a For me it is 24 bytes, but it could be slightly different for you. 对我来说,它是24个字节,但是对您来说可能略有不同。 This means that buffer can hold much more data than the struct ipheader needs. 这意味着缓冲区可以容纳的数据超过了struct ipheader所需的数据。 I haven't looked to deeply into the code, and I don't know much about socket programming. 我没有深入研究代码,对套接字编程也不太了解。 But one use for this could be to augment buffer with additional data outside of the struct. 但是,这样做的一种用途可能是在结构外部添加额外的数据来增加缓冲区。 Since you know struct ipheader takes up sizeof(ipheader) bytes you will have sizeof(char)*8192 - sizeof(ipheader) left to augment the array. 因为您知道struct ipheader占用了sizeof(ipheader)个字节,所以您将获得sizeof(char)* 8192-剩下的sizeof(ipheader)可以增加数组。

Edit: Upun further inspection, this is kinda what is happening: 编辑:Upun进一步检查,这是正在发生的事情:

struct ipheader *ip = (struct ipheader *) buffer;
struct udpheader *udp = (struct udpheader *) (buffer + sizeof(struct ipheader));

It tries to store the ip header at the beginning of the buffer, then it augments that same buffer with an udp header. 它尝试将ip标头存储在缓冲区的开头,然后使用udp标头扩展该缓冲区。 By using buffer + sizeof(struct ipheader) it makes sure that it stores the udp header after ipheader by offsetting buffer by sizeof(struct ipheader) bytes. 通过使用buffer + sizeof(struct ipheader)它通过将buffer + sizeof(struct ipheader)偏移sizeof(struct ipheader)个字节来确保它 ipheader 之后存储udp头。 Basically struct ipheader *ip points to the beginning of the buffer and struct udpheader *udp points to buffer + sizeof(struct ipheader) . 基本上struct ipheader *ip指向缓冲区的开头,而struct udpheader *udp指向buffer + sizeof(struct ipheader) I hope this makes sense. 我希望这是有道理的。 Obviously there is still a lot of space left over in buffer so you could potentially augment it even further. 显然,缓冲区中还剩下很多空间,因此您可能会进一步扩大它。

how a char array is cast into struct pointer 如何将char数组转换为struct指针

You can't do that safely. 您不能安全地这样做。 The code invokes undefined behavior: 该代码调用未定义的行为:

char buffer[PCKT_LEN];
struct ipheader *ip = (struct ipheader *) buffer;
//some code here
ip->iph_ihl = 5;
ip->iph_ver = 4;
ip->iph_tos = 16;

That code violates the strict aliasing rule . 该代码违反了严格的别名规则 That basically means memory that isn't a certain type of object can't be treated as being that type of object, with the exception that any non- char object can be treated as an array of char . 基本上,这意味着不是某种对象类型的内存不能被视为该类型的对象,除了任何非char对象都可以视为char数组。

That's not what's happening in the posted code. 那不是发布的代码中发生的事情。 In the posted code, a char array is being treated as if it were a struct ipheader . 在发布的代码中,将char数组视为是struct ipheader

The memory is not a struct ipheader - it's an array of char - so the code violates strict aliasing. 内存不是一个struct ipheader ,而是一个char数组,因此代码违反了严格的别名。

The casting from char * to struct ipheader * can also result in an improperly aligned object and violate 6.3.2.3 Pointers , paragraph 7 : char *struct ipheader *还可能导致对象对齐不正确并违反6.3.2.3指针第7段

A pointer to an object type may be converted to a pointer to a different object type. 指向对象类型的指针可以转换为指向不同对象类型的指针。 If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined. 如果结果指针未针对引用类型正确对齐,则该行为未定义。 ... ...

Code such as you've found here is unfortunately all too common as the x86-based machines that are the most common platform widely used by programmers are very forgiving of misaligned accesses, so such code tends to "work". 不幸的是,您在这里发现的代码非常普遍,因为基于x86的计算机是程序员广泛使用的最常见的平台,它们非常宽容错位的访问,因此此类代码易于“工作”。

See Structure assignment in Linux fails in ARM but succeeds in x86 for an example of a platform where it doesn't work. 请参阅Linux中的结构分配在ARM上失败,但在x86上成功在不起作用的平台上进行说明。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM