c - 作为联合成员的类型可以为该联合别名吗?
问题描述
由这个问题提示:
C11 标准规定指向联合的指针可以转换为指向其每个成员的指针。从第 6.7.2.1p17 节:
工会的规模足以容纳其最大的成员。任何时候最多可以将其中一个成员的值存储在联合对象中。 一个指向联合对象的指针,经过适当的转换,指向它的每个成员 (或者如果一个成员是一个位域,那么指向它所在的单元),反之亦然。
这意味着您可以执行以下操作:
union u {
int a;
double b;
};
union u myunion;
int *i = (int *)&u;
double *d = (double *)&u;
u.a = 2;
printf("*i=%d\n", *i);
u.b = 3.5;
printf("*d=%f\n", *d);
但是反过来呢:在上述联合的情况下, aint *
或double *
可以安全地转换为 aunion u *
吗?考虑以下代码:
#include <stdio.h>
union u {
int a;
double b;
};
void f(int isint, union u *p)
{
if (isint) {
printf("int value=%d\n", p->a);
} else {
printf("double value=%f\n", p->b);
}
}
int main()
{
int a = 3;
double b = 8.25;
f(1, (union u *)&a);
f(0, (union u *)&b);
return 0;
}
在此示例中,指向int
和的指针double
(它们都是 的成员)被传递给预期union u
为 a 的函数。union u *
一个标志被传递给函数以告诉它要访问哪个“成员”。
假设在这种情况下,访问的成员与实际传入的对象的类型匹配,上面的代码是否合法?
我在 gcc 6.3.0 上编译了这个,-O0
并且-O3
两者都给出了预期的输出:
int value=3
double value=8.250000
解决方案
在这个例子中,指向 int 和 double 的指针,它们都是 union u 的成员,被传递给一个需要 union u * 的函数。一个标志被传递给函数以告诉它要访问哪个“成员”。
假设在这种情况下,访问的成员与实际传入的对象的类型匹配,上面的代码是否合法?
您似乎将分析的重点放在工会成员类型上的严格别名规则上。然而,鉴于
union a_union {
int member;
// ...
} my_union, *my_union_pointer;
,我倾向于争辩说,除了访问成员类型的对象之外,还my_union.member
表示my_union_pointer->member
访问类型对象的存储值。union a_union
因此,如果my_union_pointer
实际上并不指向有效类型为的对象,union a_union
则确实违反了严格的别名规则——关于类型union a_union
——因此行为是未定义的。
推荐阅读
- android - 为什么 minSdkVersion 为 21 时可以编译 Android Launcher Shortcuts 代码?
- python - Python如何键入一个返回self的方法?
- java - 我的 Android github 存储库。无法上课
- html - 使用flutter在webview中显示下载的临时本地文件(png、jpg、pdf、rtf)
- php - 动作 ProductController@store 未定义,但它确实在 Laravel 8
- c# - 检查 DevOps 管道中过时的 nuget 包
- google-cloud-platform - 云任务创建期间的身份验证范围不足错误
- html - 将切换按钮的 Html 标签转换为 erb
- c# - 是否可以在 winform c# 中不使用“IntersectWith”语法检查两个对象是否发生碰撞?
- html - 网站在移动测试中无法正确查看 没有给出错误