类型转换结构指针
Type casting 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;
根据我的理解,指针 ip 现在将保存缓冲区的地址,并且 struct ipheader 成员的值现在将存储在缓冲区中。请帮助理解相同的内容。如果我是对的,那么我们如何打印存储在缓冲区中的值?
您的理解是正确的。指针 *ip 将指向缓冲区。 char buffer[PCKT_LEN] 是一个大小为 sizeof(char) * PCKT_LEN 的数组。由于 char 通常是 1 个字节长,它只是 PCKT_LEN 字节的一块内存。 PCKT_LEN 定义为 8192
存储一个 struct ipheader 所需的字节数比这少得多。尝试 int a = sizeof(ipheader)
并使用调试器查看分配给 a
的值。对我来说它是 24 个字节,但对您来说可能略有不同。这意味着 buffer 可以容纳比 struct ipheader 需要更多的数据。我没有深入研究代码,我对套接字编程了解不多。但是它的一个用途可能是使用结构之外的附加数据来扩充缓冲区。由于您知道 struct ipheader 占用 sizeof(ipheader) 字节,因此您将剩下 sizeof(char)*8192 - sizeof(ipheader) 来扩充数组。
编辑:
Upun 进一步检查,这有点像正在发生的事情:
struct ipheader *ip = (struct ipheader *) buffer;
struct udpheader *udp = (struct udpheader *) (buffer + sizeof(struct ipheader));
它尝试将 ip header 存储在缓冲区的开头,然后使用 udp header 扩充同一缓冲区。通过使用 buffer + sizeof(struct ipheader)
它确保通过将缓冲区偏移 sizeof(struct ipheader) 字节来存储 udp header after ipheader。基本上 struct ipheader *ip
指向缓冲区的开头,而 struct udpheader *udp
指向 buffer + sizeof(struct ipheader)
。我希望这是有道理的。显然,缓冲区中仍有很多 space 剩余,因此您可以进一步增加它。
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;
该代码违反了 the strict aliasing rule。这基本上意味着不是某种类型对象的内存不能被视为该类型的对象,除了任何非 char
对象都可以被视为 char
的数组.
发布的代码中并没有发生这种情况。在发布的代码中,char
数组被视为 struct ipheader
.
内存不是 struct ipheader
- 它是 char
的数组 - 因此代码违反了严格的别名。
从 char *
到 struct ipheader *
的转换也可能导致对象对齐不正确并违反 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. ...
不幸的是,您在此处找到的代码太常见了,因为基于 x86 的机器是程序员广泛使用的最常见平台,对未对齐的访问非常宽容,因此此类代码往往 "work".
请参阅 Structure assignment in Linux fails in ARM but succeeds in x86 以了解它不起作用的平台示例。
我正在尝试进入 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;
根据我的理解,指针 ip 现在将保存缓冲区的地址,并且 struct ipheader 成员的值现在将存储在缓冲区中。请帮助理解相同的内容。如果我是对的,那么我们如何打印存储在缓冲区中的值?
您的理解是正确的。指针 *ip 将指向缓冲区。 char buffer[PCKT_LEN] 是一个大小为 sizeof(char) * PCKT_LEN 的数组。由于 char 通常是 1 个字节长,它只是 PCKT_LEN 字节的一块内存。 PCKT_LEN 定义为 8192
存储一个 struct ipheader 所需的字节数比这少得多。尝试 int a = sizeof(ipheader)
并使用调试器查看分配给 a
的值。对我来说它是 24 个字节,但对您来说可能略有不同。这意味着 buffer 可以容纳比 struct ipheader 需要更多的数据。我没有深入研究代码,我对套接字编程了解不多。但是它的一个用途可能是使用结构之外的附加数据来扩充缓冲区。由于您知道 struct ipheader 占用 sizeof(ipheader) 字节,因此您将剩下 sizeof(char)*8192 - sizeof(ipheader) 来扩充数组。
编辑: Upun 进一步检查,这有点像正在发生的事情:
struct ipheader *ip = (struct ipheader *) buffer;
struct udpheader *udp = (struct udpheader *) (buffer + sizeof(struct ipheader));
它尝试将 ip header 存储在缓冲区的开头,然后使用 udp header 扩充同一缓冲区。通过使用 buffer + sizeof(struct ipheader)
它确保通过将缓冲区偏移 sizeof(struct ipheader) 字节来存储 udp header after ipheader。基本上 struct ipheader *ip
指向缓冲区的开头,而 struct udpheader *udp
指向 buffer + sizeof(struct ipheader)
。我希望这是有道理的。显然,缓冲区中仍有很多 space 剩余,因此您可以进一步增加它。
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;
该代码违反了 the strict aliasing rule。这基本上意味着不是某种类型对象的内存不能被视为该类型的对象,除了任何非 char
对象都可以被视为 char
的数组.
发布的代码中并没有发生这种情况。在发布的代码中,char
数组被视为 struct ipheader
.
内存不是 struct ipheader
- 它是 char
的数组 - 因此代码违反了严格的别名。
从 char *
到 struct ipheader *
的转换也可能导致对象对齐不正确并违反 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. ...
不幸的是,您在此处找到的代码太常见了,因为基于 x86 的机器是程序员广泛使用的最常见平台,对未对齐的访问非常宽容,因此此类代码往往 "work".
请参阅 Structure assignment in Linux fails in ARM but succeeds in x86 以了解它不起作用的平台示例。