简体   繁体   中英

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

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. 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. char buffer[PCKT_LEN] is an array of size sizeof(char) * PCKT_LEN. Since a char is usually 1 byte long it is just a chunk of memory of PCKT_LEN bytes. PCKT_LEN is defined to be 8192

The amount of bytes needed to store a struct ipheader is much less than this. Try int a = sizeof(ipheader) and use a debugger to see the value assigned to a . For me it is 24 bytes, but it could be slightly different for you. This means that buffer can hold much more data than the struct ipheader needs. 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.

Edit: Upun further inspection, this is kinda what is happening:

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. 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. Basically struct ipheader *ip points to the beginning of the buffer and struct udpheader *udp points to 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

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 .

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 .

The memory is not a struct ipheader - it's an array of char - so the code violates strict aliasing.

The casting from char * to struct ipheader * can also result in an improperly aligned object and violate 6.3.2.3 Pointers , paragraph 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".

See Structure assignment in Linux fails in ARM but succeeds in x86 for an example of a platform where it doesn't work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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