这篇文章试图说什么? 如果我使用它或不使用它会发生什么?正如它所说的那样,PUNNING类型是当您有两个不同类型的指针时,都指向同一位置。示例:
// BAD CODE uint32_t data; uint32_t* u32 = &data; uint16_t* u16 = (uint16_t*)&data; *u16 = ... // de-referencing invokes undefined behavior
该代码在C ++(和C)中调用未定义的行为,因为您不允许您通过非兼容类型的指针访问相同的存储位置(还有一些特殊例外)。这在非正式地称为“严格的混叠违规”,因为它违反了措施的混杂规则。
动作的方式是通过工会:// BAD C++ CODE
typedef union
{
uint32_t u32;
uint16_t u16 [2];
} my_type;
my_type mt;
mt.u32 = 1;
std::cout << mt.u16[0]; // access union data through another member, undefined behavior
在C ++中,这也是不确定的行为(但在C中允许并且完全罚款)。 type type的双关和混叠是独特的,但有些编译器作家似乎无法区分的概念,尽管他们在很大程度上是正交的。 type punning是指存储被写入一种类型并将其读成另一种类型的情况,通常是为了允许值解释为一组位,允许将一系列位解释为值,或者将其解释为值允许一个值用作另一种类型的表示,至少在感兴趣的部分中,其表示形式匹配。 例如,在某种情况下,后一种类型的双关语形式可能有用尽管结构的不同类型,但这些结构。 请注意,即使标准包含明确的保证,这表明后一种形式的punning被认为是有用的,但将其与别名混淆的编译器不支持此类构造。 aaliasing是指一个不同的概念,在该概念中,使用两个或多个或多个simertane-Acultive但看似无关的均值键and的概念,以彼此相互作用的方式。 给定类似:
int test1(int *p1, int *p2)
{
*p1 = 1;
*p2 = 2;
return *p1;
}
p1==p2
p1
和p2
p2
不能从
p2
[可能是在调用函数之前是由p1
创建的,但是在函数中不可能从
p2
衍生出
p1
]。 因为该标准允许在识别相同类型的lVALUE之间进行混音,但是,当上述构造在
p2
,ddite的事实时,上述构造将定义行为。 另一方面,给出了类似的东西:
p1
here,指针
p2
,
p1==p2
和
p1
显然具有与众不同的寿命,因此并非同时活跃,彼此相似。 每个指针都是独立派生的
p2
,每个指针的寿命将在下一次使用之前结束。 因此,此代码利用类型的punning来访问与a
struct s1 {int x; };
struct s2 {int x; };
union s1s2 {struct s1 v1; struct s2 v2; } uarr[100];
int test1(int i, int j)
{
int temp;
{ struct s1 *p1 = &uarr[i].v1; temp = p1->x; }
if (temp)
{ struct s2 *p2 = &uarr[j].v2; p2->x = 1; }
{ struct s1 *p3 = &uarr[i].v1; temp = p3->x; }
return temp;
}
和a
p1
的同一存储,但由于书面并不利用混血,因为对所涉及的存储的所有访问均明显从同一root-衍生得出级别对象
p2
.不幸的是,即使打算(根据理由和脚注)表示何时将事物添加到别名时,也有一些编译器以使他们的语言特征(例如常见的初始序列保证)来解释它们本质上是毫无用处的,因为他们使用Type-Access规则作为借口重写代码的借口,以删除从
p3
中删除uarr
的推导,从而引入了没有存在的位置。
完全有充分的理由使用puning。 想象您要通过串行链接传输数据,但数据是 实际上是不同类型的包装结构。 包装结构以字节数组发送,但要显示数据 这是不同类型的...
uarr
sandwer:
x = 04030201,y = 05040302,z =08070605
注意这是小末日(LSB较低记忆中的LSB)
puns会吸引大脑的双方,使其成为您的机智的锻炼。他们挑战我们对语言的不同思考,从而导致了令人满意的“啊哈”时刻。无论是简单还是复杂,双关语都证明单词可以同时既聪明又愚蠢。尝试从https://punzify.com/
探索双关语