Punning类型是一个广泛的概念,适用于任何具有类型系统和一点灵活性的语言,所以我使用维基百科的例子与Berkeley套接字:
从维基百科页面:
在Berkeley套接字界面中可以找到一个典型的类型惩罚示例.将已打开但未初始化的套接字绑定到IP地址的函数声明如下:
int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
bind函数通常调用如下:
struct sockaddr_in sa = {0};
int sockfd = ...;
sa.sin_family = AF_INET;
sa.sin_port = htons(port);
bind(sockfd, (struct sockaddr *)&sa, sizeof sa);
Run Code Online (Sandbox Code Playgroud)
Berkeley套接字库基本上依赖于以下事实:在C中,指向struct sockaddr_in的指针可以自由转换为指向struct sockaddr的指针; 此外,两种结构类型共享相同的内存布局.因此,对结构字段my_addr-> sin_family(其中my_addr的类型为struct sockaddr*)的引用实际上将引用字段sa.sin_family(其中sa的类型为struct sockaddr_in).换句话说,套接字库使用类型punning来实现一种基本的继承形式.
编辑:我没有注意到你提到尝试维基百科的编辑.我认为在这种情况下你应该拿走的是我在第一句中所说的,即"类型Punning是一个广泛的概念,适用于任何具有类型系统和一点灵活性的语言".如果你遇到问题,我会说要寻找更多的策略示例和实现(也许在C中看一下OOP来获得一些涉及的概念[它本身并不完全相同])
另一个编辑:它发生在我身上,也许你的意思是在工会的背景下打字,所以这里是一个修改了这个问题的例子,它询问了工会的目的(在这里向后工作):
union RGB
{
uint32_t color;
struct componentsTag
{
uint8_t b;
uint8_t g;
uint8_t r;
} components;
} pixel;
pixel.color = 0x020406;
uint8_t rVal = pixel.components.r; //this will equal 02
uint8_t gVal = pixel.components.g; //this will equal 04
uint8_t bVal = pixel.components.b; //this will equal 06
Run Code Online (Sandbox Code Playgroud)
这里使用类型双关语来允许访问每种颜色的各个值而无需C类型的转换.您可能想知道这是如何工作的.在内存中,union占用32位.当sockaddr_in使用该行设置时sockaddr,这些32位填充值0x020406(0x后的每对值占用8位(8*3 = 32位).
将32位分成部分的图表可能如下所示:
------------------------------------
-----| 00 | 02 | 04 | 06 |------
------------------------------------
| uint32_t color |
------------------------------------
Run Code Online (Sandbox Code Playgroud)
但组件的结构也在同一空间中占用32位.
所以现在联盟内存的完整图表是:
------------------------------------
-----| 00 | 02 | 04 | 06 |------
------------------------------------
| uint32_t color |
------------------------------------
-----| NA | r | g | b |------
------------------------------------
Run Code Online (Sandbox Code Playgroud)
注意如何my_addr->sin_family,my_addr和struct sockaddr*,所有重叠sa.sin_family.访问sa,struct sockaddr_in或color现在访问特定部分的pixel.color = 0x020406,它的一个8比特部分.正常情况下,uint32_t的转换为uint8_t只会给你uint32_t的的最低显著位,所以0x00020406,0x和06都会变得毫无意义的数字.但正如我之前所说,此处联合被用于类型惩罚,因此标准定义的转换正在被规避.
| 归档时间: |
|
| 查看次数: |
509 次 |
| 最近记录: |