在 C 中安全地将 char* 双关

2023-11-24

在开源中方案一 写道,我正在从文件中读取二进制数据(由另一个程序写入)并输出整数,双精度数, 以及其他各种数据类型。挑战之一是它需要 在两种字节序的 32 位和 64 位机器上运行,这意味着我 最终不得不做相当多的低级操作。我认识一个(非常) 关于类型双关和严格别名的一些知识,并想确保我 以正确的方式做事。

基本上,很容易从 char* 转换为各种大小的 int:

int64_t snativeint64_t(const char *buf) 
{
    /* Interpret the first 8 bytes of buf as a 64-bit int */
    return *(int64_t *) buf;
}

我有一系列支持函数可以根据需要交换字节顺序,例如 作为:

int64_t swappedint64_t(const int64_t wrongend)
{
    /* Change the endianness of a 64-bit integer */
    return (((wrongend & 0xff00000000000000LL) >> 56) |
            ((wrongend & 0x00ff000000000000LL) >> 40) |
            ((wrongend & 0x0000ff0000000000LL) >> 24) |
            ((wrongend & 0x000000ff00000000LL) >> 8)  |
            ((wrongend & 0x00000000ff000000LL) << 8)  |
            ((wrongend & 0x0000000000ff0000LL) << 24) |
            ((wrongend & 0x000000000000ff00LL) << 40) |
            ((wrongend & 0x00000000000000ffLL) << 56));
}

在运行时,程序检测机器的字节序并分配 以上之一指向函数指针:

int64_t (*slittleint64_t)(const char *);
if(littleendian) {
    slittleint64_t = snativeint64_t;
} else {
    slittleint64_t = sswappedint64_t;
}

现在,当我尝试将 char* 转换为 double 时,棘手的部分就出现了。 ID 喜欢重新使用字节序交换代码,如下所示:

union 
{
    double  d;
    int64_t i;
} int64todouble;

int64todouble.i = slittleint64_t(bufoffset);
printf("%lf", int64todouble.d);

然而,一些编译器可以优化掉“int64todouble.i”赋值 并破坏程序。有没有更安全的方法来做到这一点,同时考虑 这个程序必须保持性能优化,而且我 不喜欢编写一组并行转换来将 char* 转换为 直接双倍?如果双关的联合方法是安全的,我应该 重写我的函数(例如 snativeint64_t)来使用它?


我最终使用了史蒂夫·杰索普的答案是因为转换函数重新编写为使用 memcpy,如下所示:

int64_t snativeint64_t(const char *buf) 
{
    /* Interpret the first 8 bytes of buf as a 64-bit int */
    int64_t output;
    memcpy(&output, buf, 8);
    return output;
}

编译成与我的原始代码完全相同的汇编器:

snativeint64_t:
        movq    (%rdi), %rax
        ret

在这两个版本中,memcpy 版本更明确地表达了我想要做的事情,并且应该适用于即使是最幼稚的编译器。

亚当,你的回答也很棒,我从中学到了很多东西。感谢您发帖!


我强烈建议你阅读了解严格别名。具体来说,请参阅标记为“通过联合进行铸造”的部分。它有许多非常好的例子。虽然该文章发表在有关 Cell 处理器的网站上并使用 PPC 汇编示例,但几乎所有内容都同样适用于其他架构,包括 x86。

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

在 C 中安全地将 char* 双关 的相关文章

  • “构建”构建我的项目,“构建解决方案”则不构建

    我刚刚开始使用VS2010 我有一个较大的解决方案 已从 VS2008 成功迁移 我已将一个名为 Test 的控制台应用程序项目添加到解决方案中 选择构建 gt 构建解决方案不编译新项目 选择构建 gt 构建测试确实构建了项目 在失败的情况
  • 在结构中使用 typedef 枚举并避免类型混合警告

    我正在使用 C99 我的编译器是 IAR Embedded workbench 但我认为这个问题对于其他一些编译器也有效 我有一个 typedef 枚举 其中包含一些项目 并且我向该新类型的结构添加了一个元素 typedef enum fo
  • 用于检查类是否具有运算符/成员的 C++ 类型特征[重复]

    这个问题在这里已经有答案了 可能的重复 是否可以编写一个 C 模板来检查函数是否存在 https stackoverflow com questions 257288 is it possible to write a c template
  • 查找c中结构元素的偏移量

    struct a struct b int i float j x struct c int k float l y z 谁能解释一下如何找到偏移量int k这样我们就可以找到地址int i Use offsetof 找到从开始处的偏移量z
  • 将 VSIX 功能添加到 C# 类库

    我有一个现有的单文件生成器 位于 C 类库中 如何将 VSIX 项目级功能添加到此项目 最终目标是编译我的类库项目并获得 VSIX 我实际上是在回答我自己的问题 这与Visual Studio 2017 中的单文件生成器更改 https s
  • C++ OpenSSL 导出私钥

    到目前为止 我成功地使用了 SSL 但遇到了令人困惑的障碍 我生成了 RSA 密钥对 之前使用 PEM write bio RSAPrivateKey 来导出它们 然而 手册页声称该格式已经过时 实际上它看起来与通常的 PEM 格式不同 相
  • 带动态元素的 WPF 启动屏幕。如何?

    我是 WPF 新手 我需要一些帮助 我有一个加载缓慢的 WPF 应用程序 因此我显示启动屏幕作为权宜之计 但是 我希望能够在每次运行时更改屏幕 并在文本区域中显示不同的引言 这是一个生产力应用程序 所以我将使用非愚蠢但激励性的引言 当然 如
  • 使用 Bearer Token 访问 IdentityServer4 上受保护的 API

    我试图寻找此问题的解决方案 但尚未找到正确的搜索文本 我的问题是 如何配置我的 IdentityServer 以便它也可以接受 授权带有 BearerTokens 的 Api 请求 我已经配置并运行了 IdentityServer4 我还在
  • 如何序列化/反序列化自定义数据集

    我有一个 winforms 应用程序 它使用强类型的自定义数据集来保存数据进行处理 它由数据库中的数据填充 我有一个用户控件 它接受任何自定义数据集并在数据网格中显示内容 这用于测试和调试 为了使控件可重用 我将自定义数据集视为普通的 Sy
  • 垃圾收集器是否在单独的进程中运行?

    垃圾收集器是否在单独的进程中启动 例如 如果我们尝试测量某段代码所花费的进程时间 并且在此期间垃圾收集器开始收集 它会在新进程上启动还是在同一进程中启动 它的工作原理如下吗 Code Process 1 gt Garbage Collect
  • 什么时候虚拟继承是一个好的设计? [复制]

    这个问题在这里已经有答案了 EDIT3 请务必在回答之前清楚地了解我要问的内容 有 EDIT2 和很多评论 有 或曾经 有很多答案清楚地表明了对问题的误解 我知道这也是我的错 对此感到抱歉 嗨 我查看了有关虚拟继承的问题 class B p
  • Windows 窗体:如果文本太长,请添加新行到标签

    我正在使用 C 有时 从网络服务返回的文本 我在标签中显示 太长 并且会在表单边缘被截断 如果标签不适合表单 是否有一种简单的方法可以在标签中添加换行符 Thanks 如果您将标签设置为autosize 它会随着您输入的任何文本自动增长 为
  • 覆盖子类中的字段或属性

    我有一个抽象基类 我想声明一个字段或属性 该字段或属性在从该父类继承的每个类中具有不同的值 我想在基类中定义它 以便我可以在基类方法中引用它 例如覆盖 ToString 来表示 此对象的类型为 property field 我有三种方法可以
  • 如何使用 C# / .Net 将文件列表从 AWS S3 下载到我的设备?

    我希望下载存储在 S3 中的多个图像 但目前如果我只能下载一个就足够了 我有对象路径的信息 当我运行以下代码时 出现此错误 遇到错误 消息 读取对象时 访问被拒绝 我首先做一个亚马逊S3客户端基于我的密钥和访问配置的对象连接到服务器 然后创
  • 如何从两个不同的项目中获取文件夹的相对路径

    我有两个项目和一个共享库 用于从此文件夹加载图像 C MainProject Project1 Images 项目1的文件夹 C MainProject Project1 Files Bin x86 Debug 其中有project1 ex
  • 混合 ExecutionContext.SuppressFlow 和任务时 AsyncLocal.Value 出现意外值

    在应用程序中 由于 AsyncLocal 的错误 意外值 我遇到了奇怪的行为 尽管我抑制了执行上下文的流程 但 AsyncLocal Value 属性有时不会在新生成的任务的执行范围内重置 下面我创建了一个最小的可重现示例来演示该问题 pr
  • 测试用例执行完成后,无论是否通过,如何将测试用例结果保存在变量中?

    我正在使用 NUNIT 在 Visual Studio 中使用 Selenium WebDriver 测试用例的代码是 我想在执行测试用例后立即在变量中记录测试用例通过或失败的情况 我怎样才能实现这一点 NUnit 假设您使用 NUnit
  • 哪种 C 数据类型可以表示 40 位二进制数?

    我需要表示一个40位的二进制数 应该使用哪种 C 数据类型来处理这个问题 如果您使用的是 C99 或 C11 兼容编译器 则使用int least64 t以获得最大的兼容性 或者 如果您想要无符号类型 uint least64 t 这些都定
  • C# - OutOfMemoryException 在 JSON 文件上保存列表

    我正在尝试保存压力图的流数据 基本上我有一个压力矩阵定义为 double pressureMatrix new double e Data GetLength 0 e Data GetLength 1 基本上 我得到了其中之一pressur
  • Windows 和 Linux 上的线程

    我在互联网上看到过在 Windows 上使用 C 制作多线程应用程序的教程 以及在 Linux 上执行相同操作的其他教程 但不能同时用于两者 是否存在即使在 Linux 或 Windows 上编译也能工作的函数 您需要使用一个包含两者的实现

随机推荐

  • Java Swing 的地图 API

    我想在 swing 应用程序中可视化地理地图 我只找到了 swingx 地图 api 你还知道其他开源地图API吗 Try Geotools 它有一个很好的地理空间数据API和工具
  • Swift Mac OSX NSButton 标题颜色

    我想知道如何在 swift 中将标题颜色更改为 NSButton 我在 Objective C 中看到了很多示例 但我认为 swift 中的实现是不同的 任何人都可以为我提供一个示例吗 试试这个viewDidLoad或某处 在斯威夫特 3
  • 如何解决 MS Access 2010 中的“条件表达式中的数据类型不匹配”错误? [关闭]

    Closed 这个问题需要调试细节 目前不接受答案 我正在尝试对 MS Access 数据库中的报告进行故障排除 该文件是由在我加入我所工作的组织之前担任我的职位的人员构建的 报告抛出错误 条件表达式中的数据类型不匹配 这使我相信导入数据库
  • 运行时主机到底是什么?

    Runtime Host 的确切定义是什么 来自MSDN 公共语言运行时被设计为支持各种不同类型的应用程序 从Web 服务器应用程序到具有传统的丰富Windows 用户界面的应用程序 每种类型的应用程序都需要运行时主机来启动它 运行时主机将
  • 如何在 Java 中检测 Image 对象上的鼠标单击事件?

    实施 国王角Java 中的 美化的多人纸牌游戏 我试图允许玩家将一张牌 图像 从他们的手上拖到桌子上的其他地方 问题在于玩家的手是 扇形 的 因此纸牌的图像会旋转并且重叠 这是一手牌的例子 我考虑过让每张卡都成为JPanel 但问题是我必须
  • C++ 先前的定义错误

    因此 感谢这个网站 我找到了之前问题的答案 我正在向 GNU automake 项目中的类添加一个函数 该函数使用指向doc目的 依赖项包含在 Makefile am 文件中以包含doc h and plsa h按各自的顺序 但是 当我编译
  • 为什么这段代码不抛出 NullPointerException

    我只是和我的朋友讨论使用类名调用静态方法 并尝试了这段代码 并期望它在运行时抛出 NPE 但事实证明它没有作用 我只是想了解执行顺序 public class One public static void method System out
  • NSObject.BroadSystemFontWeights 警告消息是什么意思?

    我最近将 XCode 更新到 7 0 并收到以下警告消息 Xcode IDEInterfaceBuilder Cocoa NSObject BroadSystemFontWeights 这是什么意思以及如何摆脱它 当我将字体粗细设置为时 我
  • 使用 document.execCommand('copy') 复制到剪贴板因大文本而失败

    我使用隐藏文本区域来放置一些文本 选择它 然后使用 document execCommand 将其复制到剪贴板 这通常有效 但当文本很大时会失败 返回 false 在 Chrome v55 中 它似乎在 180K 字符左右失败 通过这种方式
  • 如何使用 Haskell 向量编写并行代码?

    一只手 在 Haskell 中Vector a似乎是用作数字数组的首选类型 甚至还有一个 不完整的 矢量教程 另一方面 Control Parallel Strategies主要是根据Traversable 矢量库不提供这些实例 的最小完整
  • 如何批量更新 postgres 中的单个列 5500 万条记录

    我想更新 postgres 表的一列 记录大约有 5500 万条 因此我们需要批量更新 10000 条记录 注意 我们要更新所有行 但我们不想锁定我们的桌子 我正在尝试以下查询 Update account set name Some na
  • git 子模块 foreach 不工作

    我想弄清楚为什么git submodule foreach命令对我不起作用 我克隆了一个 git 存储库 它有几个子模块 我想立即初始化并更新所有子模块以获取子模块源 但无论我尝试 git submodule foreach 都不适合我 我
  • 如何在地址栏上显示标志?

    我想在地址栏上显示徽标 但它仅在标题旁边的选项卡上可见 简短的回答 是的 这就是许多浏览器的工作原理 火狐浏览器 http msujaws wordpress com 2012 04 23 an update to site identit
  • 为什么实现接口的类中的通用成员函数不能采用类(而不是接口)类型的参数?

    考虑一个接口IDog用方法likes
  • 通过多列进行 SQL 过滤

    我有一个 MySql 表 我想查询其中的行pairs列位于特定集合中 例如 假设我的表如下所示 id f1 f2 1 a 20 2 b 20 3 a 30 4 b 20 5 c 20 现在 我希望提取其中该对的行 f1 f2 是 a 30
  • 在 R 中:通过对范围内的值进行布尔比较来索引向量:index==c(min : max)

    在 R 中 假设我们有一个向量 area c rep c 26 30 5 rep c 500 504 5 rep c 550 554 5 rep c 76 80 5 和另一个向量yield c 1 100 现在 假设我想像这样建立索引 gt
  • 如何在 Selenium 中等待警报框执行操作?

    我按下取消按钮 根据我的代码 它正在检查一些文本 在 Chrome 和 Firefox 中 它工作正常 但在 IE 中 在警报框上执行操作需要时间 但代码会移动到下一行 所以我想要一些代码停止 直到在警报框中执行操作 然后才进入下一步 我正
  • Mercurial CGI (hgweb.cgi) 失败

    我在虚拟机上运行的 Win 2k8 R2 上安装了 Mercurial 1 8 1 Python 2 6 6 我尝试过从 msi 源代码和使用 tortisehg 安装 命令行 Hg 工作正常 但运行 hgweb cgi 时出现相同的错误
  • 加载 YOLO:标量变量的索引无效

    收到 IndexError 错误 yolo layers 行上标量变量的索引无效 network cv2 dnn readNetFromDarknet yolov3 cfg yolov3 weights layers network get
  • 在 C 中安全地将 char* 双关

    在开源中方案一 写道 我正在从文件中读取二进制数据 由另一个程序写入 并输出整数 双精度数 以及其他各种数据类型 挑战之一是它需要 在两种字节序的 32 位和 64 位机器上运行 这意味着我 最终不得不做相当多的低级操作 我认识一个 非常