在 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* 双关 的相关文章

  • 无法使用 strptime() 获取秒数

    我收到 YYYY MM DDThh mm ss S Z hh mm 这种格式的日期时间 我正在尝试使用复制该值strptime如下所示 struct tm time 0 char pEnd strptime datetime Y m dT
  • 在 LINQ 查询中返回不带时间的日期

    我正在编写一个查询 我想计算按日期联系我们的呼叫中心的次数 看起来很简单 但由于联系日期字段是日期时间字段 我得到了时间 因此当我按联系日期 时间 分组时 每个联系日期实例的计数为 1 所以 我想只按日期分组 而不按时间分组 下面是我用来查
  • 属性对象什么时候创建?

    由于属性实际上只是附加到程序集的元数据 这是否意味着属性对象仅根据请求创建 例如当您调用 GetCustomAttributes 时 或者它们是在创建对象时创建的 或者 前两个的组合 在由于 CLR 的属性扫描而创建对象时创建 从 CLR
  • 在 Xamarin Android 中将图像从 URL 异步加载到 ImageView 中

    我有一个包含多个项目的 ListView 列表中的每个项目都应该有一个与之关联的图像 我创建了一个数组适配器来保存每个列表项并具有我希望加载的图像的 url 我正在尝试使用 Web 请求异步加载图像 并设置图像并在加载后在视图中更新它 但视
  • FFMPEG Seeking 带来音频伪影

    我正在使用 ffmpeg 实现音频解码器 在读取音频甚至搜索已经可以工作时 我无法找到一种在搜索后清除缓冲区的方法 因此当应用程序在搜索后立即开始读取音频时 我没有任何工件 avcodec flush buffers似乎对内部缓冲区没有任何
  • 跨多个控件共享事件处理程序

    在我用 C 编写的 Windows 窗体应用程序中 我有一堆按钮 当用户的鼠标悬停在按钮上时 我希望按钮的边框发生变化 目前我有以下多个实例 每个按钮一个副本 private void btnStopServer MouseEnter ob
  • 将字符串从非托管代码传递到托管

    我在将字符串从非托管代码传递到托管代码时遇到问题 在我的非托管类中 非托管类 cpp 我有一个来自托管代码的函数指针 TESTCALLBACK FUNCTION testCbFunc TESTCALLBACK FUNCTION 接受一个字符
  • 使用 C# 在 WinRT 中获取可用磁盘空间

    DllImport kernel32 dll SetLastError true static extern bool GetDiskFreeSpaceEx string lpDirectoryName out ulong lpFreeBy
  • c 中的错误:声明隐藏了全局范围内的变量

    当我尝试编译以下代码时 我收到此错误消息 错误 声明隐藏了全局范围内的变量 无效迭代器 节点 根 我不明白我到底在哪里隐藏或隐藏了之前声明的全局变量 我怎样才能解决这个问题 typedef node typedef struct node
  • .Net Core / 控制台应用程序 / 配置 / XML

    我第一次尝试使用新的 ConfigurationBuilder 和选项模式进入 Net Core 库 这里有很多很好的例子 https docs asp net en latest fundamentals configuration ht
  • 在 ASP.Net Core 2.0 中导出到 Excel

    我曾经使用下面的代码在 ASP NET MVC 中将数据导出到 Excel Response AppendHeader content disposition attachment filename ExportedHtml xls Res
  • 我的 strlcpy 版本

    海湾合作委员会 4 4 4 c89 我的程序做了很多字符串处理 我不想使用 strncpy 因为它不会终止 我不能使用 strlcpy 因为它不可移植 只是几个问题 我怎样才能让我的函数正常运行 以确保它完全安全稳定 单元测试 这对于生产来
  • 像“1$”这样的位置参数如何与 printf() 一起使用?

    By man I find printf d width num and printf 2 1 d width num 是等价的 但在我看来 第二种风格应该与以下相同 printf d num width 然而通过测试似乎man是对的 为什
  • 更改窗口的内容 (WPF)

    我创建了一个简单的 WPF 应用程序 它有两个 Windows 用户在第一个窗口中填写一些信息 然后单击 确定 这会将他们带到第二个窗口 这工作正常 但我试图将两个窗口合并到一个窗口中 这样只是内容发生了变化 我设法找到了这个更改窗口内容时
  • .NET 选项将视频文件流式传输为网络摄像头图像

    我有兴趣开发一个应用程序 它允许我从 xml 构建视频列表 包含视频标题 持续时间等 并将该列表作为我的网络摄像头流播放 这意味着 如果我要访问 ustream tv 或在实时通讯软件上激活我的网络摄像头 我的视频播放列表将注册为我的活动网
  • 可空属性与可空局部变量

    我对以下行为感到困惑Nullable types class TestClass public int value 0 TestClass test new TestClass Now Nullable GetUnderlyingType
  • AccessViolationException 未处理

    我正在尝试使用史蒂夫 桑德森的博客文章 http blog stevensanderson com 2010 01 28 editing a variable length list aspnet mvc 2 style 为了在我的 ASP
  • 检查 url 是否指向文件或页面

    我们需要以下内容 如果文件确实是文件 则从 URL 下载该文件 否则 如果它是一个页面 则什么也不做 举个简单的例子 我有以下命令来下载文件 My Computer Network DownloadFile http www wired c
  • 将应用程序从 Microsoft Access 迁移到 VB 或 C#.NET

    我目前正试图说服管理层需要将我们的应用程序之一移植到 NET 该应用程序已经发展成为 Access 中的一个庞然大物 SQL 后端 拥有 700 个链接表 650 个表单 子表单 130 个模块和 850 个查询 我几乎知道这样做的所有主要
  • 为什么 strtok 会导致分段错误?

    为什么下面的代码给出了Seg 最后一行有问题吗 char m ReadName printf nRead String s n m Writes OK char token token strtok m 如前所述 读取字符串打印没有问题 但

随机推荐

  • 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 位机器上运行 这意味着我 最终不得不做相当多的低级操作 我认识一个 非常