这种类型的双关语定义明确吗?

2023-12-12

阅读引用这个答案关于严格的别名规则,我在 C++11 中看到以下内容:

如果程序尝试通过以下类型之一以外的泛左值访问对象的存储值,则行为未定义:

  • ...

  • 聚合或联合类型,其元素或非静态数据成员中包括上述类型之一(递归地包括子聚合或包含的联合的元素或非静态数据成员),

  • ...

所以我认为这意味着以下代码不会违反严格的别名规则:

#include <iostream>
#include <cstdint>
#include <climits>
#include <limits>

struct PunnerToUInt32
{
    std::uint32_t ui32;
    float fl;
};

int main()
{
    static_assert(std::numeric_limits<float>::is_iec559 &&
                  sizeof(float)==4 && CHAR_BIT==8,"Oops");
    float x;
    std::uint32_t* p_x_as_uint32=&reinterpret_cast<PunnerToUInt32*>(&x)->ui32;
    *p_x_as_uint32=5;
    std::cout << x << "\n";
}

这样,严格的别名规则就满足了。由于任何其他原因,这仍然表现出未定义的行为吗?


你不可以做这个:&reinterpret_cast<PunnerToUInt32*>(&x)

规则关于reinterpret_cast state:

当指向动态类型为的对象的指针或引用时DynamicType is reinterpret_cast(或 C 风格转换)到不同类型对象的指针或引用AliasedType,强制转换始终会成功,但如果满足以下条件之一,则生成的指针或引用只能用于访问对象:

  • AliasedType是(可能符合简历要求)DynamicType
  • AliasedType and DynamicType都是(可能是多级的,可能在每个级别都有 cv 限定的)指向同一类型的指针T
  • AliasedType是(可能是 cv 限定的)有符号或无符号变体DynamicType
  • AliasedType是聚合类型或联合类型,它将上述类型之一保存为元素或非静态成员(递归地包括子聚合的元素和所包含联合的非静态数据成员):这使得可以安全地获取给定指向其非静态成员或元素的指针,指向结构或联合的可用指针。
  • AliasedType是(可能是 cv 限定的)基类DynamicType
  • AliasedType is char or unsigned char:这允许检查任何对象的对象表示作为数组unsigned char

因为这些都不适合组合DynamicType being float and AliasedType being PunnerToUInt32该指针可能无法用于访问您正在执行的操作的对象。使行为未定义。

欲了解更多信息,请参阅:为什么在相同大小的类型之间进行强制转换时,reinterpret_cast 不强制使用 copy_n?

EDIT:

Breaking down the 4th bullet int bite size chunks yields:

  1. "AliasedType"
    这里取为PunnerToUInt32
  2. “是聚合类型还是联合类型”
    PunnerToUInt32符合资格,因为它符合资格聚合类型:

    • 数组类型
    • class type (typically, struct or union), that has
      • 没有私有或受保护的非静态数据成员
      • 没有用户提供的构造函数,包括从公共基类继承的构造函数(允许显式默认或删除的构造函数)
      • 没有虚拟、私有或受保护的基类
      • 没有虚拟成员函数
  3. “它将上述类型之一保存为元素或非静态成员(递归地包括子聚合的元素和所包含联合的非静态数据成员)”
    Again PunnerToUInt32因其资格float fl member

  4. “这使得获得指向结构或联合的可用指针变得安全”
    这是最终正确的部分AliassedType is a PunnerToUInt32
  5. “给定一个指向其非静态成员或元素的指针”
    这是一种违规行为,因为DynamicType这是x不是以下成员PunnerToUInt32

因为违反了第5部分,对此指针进行操作是未定义的行为。

如果您喜欢一些推荐读物,您可以查看空基地优化如果没有,我会在这里给你主要的相关性:

标准布局类型需要空基优化,以维持指向标准布局对象的指针的要求,使用reinterpret_cast, 指向其初始成员

Thus you could exploit reinterpret_cast's 4th bullet by doing this:

PunnerToUInt32 x = {13, 42.0F};
auto y = reinterpret_cast<PunnerToUInt32*>(&x.ui32);

Live Example

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

这种类型的双关语定义明确吗? 的相关文章

  • 查找哪些页面不再与写入时复制共享

    假设我在 Linux 中有一个进程 我从中fork 另一个相同的过程 后forking 因为原始进程将开始写入内存 Linux写时复制机制将为进程提供与分叉进程使用的不同的唯一物理内存页 在执行的某个时刻 我如何知道原始进程的哪些页面已被写
  • 使用具有现有访问令牌的 Google API .NET 客户端

    用例如下 移动应用程序正在通过 Google 对用户进行身份验证 并且在某些时候 我们需要将用户的视频发布到他的 YouTube 帐户 出于实际原因 实际发布应该由后端完成 已经存储在那里的大文件 由于用户已经通过应用程序的身份验证 因此应
  • C#动态支持吗?

    看完之后这个帖子 https stackoverflow com questions 2674906 when should one use dynamic keyword in c sharp 4 0k和链接 我还有 2 个问题 问题 1
  • 如何在 Android NDK 中创建新的 NativeWindow 而无需 Android 操作系统源代码?

    我想编译一个 Android OpenGL 控制台应用程序 您可以直接从控制台启动 Android x86 运行 或者从 Android x86 GUI 内的 Android 终端应用程序运行 这个帖子 如何在 Android NDK 中创
  • 从多个类访问串行端口

    我正在尝试使用串行端口在 arduino 和 C 程序之间进行通信 我对 C 编程有点陌生 该程序有多种用户控制形式 每一个都需要访问串口来发送数据 我需要做的就是从每个类的主窗体中写入串行端口 我了解如何设置和写入串行端口 这是我的 Fo
  • 如何从 C# 控制器重定向到外部 url

    我使用 C 控制器作为网络服务 在其中我想将用户重定向到外部网址 我该怎么做 Tried System Web HttpContext Current Response Redirect 但没有成功 使用控制器的重定向 http msdn
  • 检查算术运算中的溢出情况[重复]

    这个问题在这里已经有答案了 可能的重复 检测 C C 中整数溢出的最佳方法 https stackoverflow com questions 199333 best way to detect integer overflow in c
  • Qt 创建布局并动态添加小部件到布局

    我正在尝试在 MainWindow 类中动态创建布局 我有四个框架 它们是用网格布局对象放置的 每个框架都包含一个自定义的 ClockWidget 我希望 ClockWidget 对象在调整主窗口大小时相应地调整大小 因此我需要将它们添加到
  • 在非活动联合成员上使用“std::addressof”是否定义明确[重复]

    这个问题在这里已经有答案了 下面的代码是尝试实现constexpr的版本offsetof在 C 11 中 它可以在 gcc 7 2 0 和 clang 5 0 0 中编译 这取决于申请std addressof工会非活跃成员的成员 这是明确
  • 生产代码中的 LRU 实现

    我有一些 C 代码 需要使用 LRU 技术实现缓存替换 目前我知道两种实现LRU缓存替换的方法 每次访问缓存数据时使用时间戳 最后比较替换时的时间戳 使用缓存项的堆栈 如果最近访问过它们 则将它们移动到顶部 因此最后底部将包含 LRU 候选
  • 当“int”处于最大值并使用 postfix ++ 进行测试时,代码定义良好吗?

    示例 未定义行为的一个示例是整数溢出的行为 C11dr 3 4 3 3 int溢出是未定义的行为 但这是否适用于存在循环的以下内容 并且不使用现在超出范围的副作用i 特别是 这是否后缀增量规格帮助 结果的值计算在副作用之前排序 更新操作数的
  • 在 C 中使用 GNU automake 中的解析器

    我是 GNU autotools 的新手 在我的项目中使用了 lex 和 yacc 解析器 将它们作为 makefile am 中的源代码会产生以下错误 配置 in AC CHECK PROGS YACC bison yacc none i
  • 当我“绘制”线条时,如何将点平均分配到 LineRenderer 的宽度曲线?

    我正在使用线条渲染器创建一个 绘图 应用程序 现在我尝试使用线条渲染器上的宽度曲线启用笔压 问题在于 AnimationCurve 的 时间 值 水平轴 从 0 标准化为 1 因此我不能在每次添加位置时都在其末尾添加一个值 除非有一个我不知
  • 将代码拆分为标头/源文件

    我从 Asio 的示例页面中获取了以下代码 class tcp connection public boost enable shared from this
  • 是否可以有一个 out ParameterExpression?

    我想定义一个 Lambda 表达式out范围 有可能做到吗 下面是我尝试过的 C Net 4 0 控制台应用程序的代码片段 正如您在 procedure25 中看到的 我可以使用 lambda 表达式来定义具有输出参数的委托 但是 当我想使
  • 剪贴板在 .NET 3.5 和 4 中的行为有所不同,但为什么呢?

    我们最近将一个非常大的项目从 NET Framework 3 5 升级到 4 最初一切似乎都工作正常 但现在复制粘贴操作开始出现错误 我已经成功制作了一个小型的可复制应用程序 它显示了 NET 3 5 和 4 中的不同行为 我还找到了一种解
  • 转到定义:“无法导航到插入符号下的符号。”

    这个问题的答案是社区努力 help privileges edit community wiki 编辑现有答案以改进这篇文章 目前不接受新的答案或互动 我今天突然开始在我的项目中遇到一个问题 单击 转到定义 会出现一个奇怪的错误 无法导航到
  • 实例化 Microsoft.Office.Interop.Excel.Application 对象时出现错误:800700c1

    实例化 Microsoft Office Interop Excel Application 以从 winforms 应用程序生成 Excel 时 出现以下错误 这之前是有效的 但突然间它停止工作了 尽管代码和 Excel 版本没有变化 我
  • 是否可以在 C# 中强制接口实现为虚拟?

    我今天遇到了一个问题 试图重写尚未声明为虚拟的接口方法的实现 在这种情况下 我无法更改接口或基本实现 而必须尝试其他方法 但我想知道是否有一种方法可以强制类使用虚拟方法实现接口 Example interface IBuilder
  • 匿名结构体作为返回类型

    下面的代码编译得很好VC 19 00 23506 http rextester com GMUP11493 标志 Wall WX Za 与VC 19 10 25109 0 标志 Wall WX Za permissive 这可以在以下位置检

随机推荐