昨晚帮导师从指令中恢复图像的时候,导师要我转换成raw格式,也就是记录图像像素的二进制序列,然后反复强调让我注意大端小端。当时我也没在意,用ofstream的write方法一个个地写进去,发现有部分数据存储顺序和其他的不一致。由于时间要紧,我立刻试了下FILE*然后用"wb"模式打开文件来写,刚好要求的也是小端(因为我的win7系统就是小端存储),结果对了当时也就没管为什么之前C++的ofstream只有部分正确了。

查看了官方文档 http://www.cplusplus.com/reference/fstream/ofstream/open/

open的第二个参数是打开模式的选项,其中有一个是ios_base::binary,代表二进制读写,我没有加上这个选项所以才会在写入二进制文件时出现问题。设置这个选项在写入二进制文件的时候就会和系统存储顺序一样了。

ofstream fout;

fout.open("image2.raw", ios_base::binary);

想起我之前也踩过fopen的坑,linux下不区分文本文件和二进制文件,所以"r"和"w"通用,但是windows下区分这两者,于是要用"rb"和"wb"。而C++为了便于跨平台,为了这种区分文本和二进制的系统加上了binary打开方式。

说起来这里我用的ios_base::binary是没问题的,但是官网ofstream::write()函数的示例代码用的是ofstream::binary,看了眼微软的实现,ofstream直接继承的ios_base的binary字段,所以两者是等价的。考虑设计者在设计的时候可能会认为继承自ios_base的类会做些修改吧,这里用ofstream::binary更为妥当。

再回到大端小端的问题,如果是要跨平台地按照小端顺序写入文件是怎样呢?因为可能你在小端机器上写入的,在大端机器上读取的就会是错误的数值。

网络编程中处理这个的手段是用htonl和htons库函数,通过隐藏底层细节的转换函数,把多字节整型统一按照网络字节序(大端)来存储。但是有时候仍然需要使用小端来存储,所以还是要会手写转换函数,这里以小端为例。

比如对4字节整型:0x11223344,转换成小端是:0x44 0x33 0x22 0x11。

0x44 = 0x11223344 & 0xFF

0x33 = (0x11223344 & 0xFF00) >> 8

0x22 = (0x11223344 & 0xFF0000) >> 16

0x11 = (0x11223344 & 0xFF000000) >> 24

另外,可以发现0xFF00即0xFF<<8,因此,可以很自然地用一个循环实现这个逻辑。

对于2字节和8字节的整型也是类似,所以可以用一个简单的函数模板来实现。

#include

template // T must be integer type

T to_little_endian(T x)

{

size_t n = sizeof(T) / sizeof(uint8_t); // 2,4,8

T res;

uint8_t* p = (uint8_t*) &res;

for (size_t i = ; i < n; i++)

{

int offset = * i;

p[i] = (x & (0xFF << offset)) >> offset;

}

return res;

}

看似这个实现没什么问题,来写份测试代码看看

uint16_t i1 = 0x1122;

uint32_t i2 = 0x11223344;

uint64_t i3 = 0x1122334455667788;

printf("%04x => %04x\n", i1, to_little_endian(i1));

printf("%08x => %08x\n", i2, to_little_endian(i2));

printf("%016lx => %016lx\n", i3, to_little_endian(i3));

结果如下,8字节整型转换出错

1122 => 1122

11223344 => 11223344

1122334455667788 => 1100000055667788

调试发现原因是0xFF,这个整型字面值的默认类型是int,对于类型uint64_t(unsigned long long),int向左移位会造成溢出。所以需要显式地把0xFF转换为uint64_t类型。对于这个函数模板而言,0xFF << offset表示的是x将低位全部置为0,并舍弃高位,所以结果是不大于x的,那么这里0xFF只用转换成T即可。

修改后的代码:

template // T must be integer type

T to_little_endian(T x)

{

size_t n = sizeof(T) / sizeof(uint8_t); // 2,4,8

T res;

uint8_t* p = (uint8_t*) &res;

T mask = static_cast(0xFF);

for (size_t i = ; i < n; i++)

{

int offset = * i;

p[i] = (x & (mask << offset)) >> offset;

}

return res;

}

至于大端,只需要把int offset = 8 * i改成int offset = 8 * (n - i - 1)即可。

OK,说实话C++的坑真是不少,类型方面的陷阱真不少。刚才用cout打印uint8_t类型的时候也是,必须强制转换成int,因为uint8_t和char都是1字节,所以operator<

整型,长整型,无符号整型等 大端和小端(Big endian and Little endian)

一.大端和小端的问题 对于整型.长整型.无符号整型等数据类型,Big endian 认为第一个字节是最高位字节(按照从低地址到高地址的顺序存放数据的高位字节到低位字节):而 Little endian ...

C语言--测试电脑存储模式(大端存储OR小端存储)

相信大家都知道大端存储和小端存储的概念,这在平时,我们一般不用考虑,但是,在某些场合,这些概念就显得很重要,比如,在 Socket 通信时,我们的电脑是小端存储模式,可是传送数据或者消息给对方电脑时, ...

大端和小端(Big endian and Little endian)

一.大端和小端的问题 对于整型.长整型等数据类型,Big endian 认为第一个字节是最高位字节(按照从低地址到高地址的顺序存放数据的高位字节到低位字节):而 Little endian 则相反,它 ...

大端和小端(big endian little endian)

一.大端和小端的问题 对于整型.长整型等数据类型,Big endian 认为第一个字节是最高位字节(按照从低地址到高地址的顺序存放数据的高位字节到低位字节):而 Little endian 则相反,它 ...

转!大端模式&amp&semi;小端模式

大端模式&小端模式   在C语言中除了8位的char型之外,还有16位的short型,32位的long型(要看具体的编译器),对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器 ...

03大端和小端(Big endian and Little endian)

1.大端和小端的问题 ​ 对于整型.长整型等数据类型,Big endian 认为第一个字节是最高位字节(按照从低地址到高地址的顺序存放数据的高位字节到低位字节),而 Little endian 则相反 ...

Java中如何判断当前环境是大端字节顺序还是小端字节顺序

Java非字节类型的基本类型,除了布尔型都是由组合在一起的几个字节组成的.这些数据类 型及其大小总结在表 2-1 中. 表:基本数据类型及其大小 数据类型 大小(以字节表示) Byte 1 Char ...

大端模式&amp&semi;小端模式、主机序&amp&semi;网络序、入栈地址高低问题

一.大端模式&小端模式 所谓的“大端模式”,是指数据的低位(就是权值较小的后面那几位)保存在内存的高地址中,而数据的高位,保存在内存的低地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处 ...

判断CPU是大端还是小端模式

在小端模式中,低位字节放在低地址,高位字节放在高地址:在大端模式中,低位字节放在高地址,高位字节放在低地址.big-endian和little-endian,51单片机是典型的大端模式,Intel电脑 ...

随机推荐

数值的三种表示--C语言

在C语言中,数值常数可以是3中形式: (1)在数值前面加0表示的是8进制数据: (2)在数字前面加0x表示的是16进制数: (3)在数值前面什么也不加,表示的是10进制数值.        目前C语言 ...

CF 197 DIV2 Xenia and Bit Operations 线段树

线段树!!1A 代码如下: #include #include #define lson i<<1 #define rson i ...

跟我一起学习VIM - The Life Changing Editor

前两天同事让我在小组内部分享一下VIM,于是我花了一点时间写了个简短的教程.虽然准备有限,但分享过程中大家大多带着一种惊叹的表情,原来编辑器可以这样强大,这算是对我多年来使用VIM的最大鼓舞吧.所以分 ...

CentOS升级git

1.首先查看下当前的版本 [root@localhost ~]# git --versiongit version 1.8.2.1 2.尝试进行升级 [root@localhost ~]# yum u ...

python中enumerate的使用

在python的应用中,当我们使用一个数组或者列表的时候既要遍历索引又要遍历元素的时候通常的做法是这样的: >>> lsi = [1,2,3,4,5,6,7,8,9] >&gt ...

Python进阶&lpar;面向对象编程基础&rpar;&lpar;一&rpar;

鉴于昨天被类和函数折腾得晕头转向,今特把类的知识翻出来温习. 1.定义类并创建实力对象 #!/usr/bin/env python # -*- coding:utf-8 -*- __author__ ...

CodeForces 645A Amity Assessment

简单模拟. #pragma comment(linker, "/STACK:1024000000,1024000000") #include #incl ...

preg&lowbar;&ast;匹配的字符串长度限制问题以及nginx,php上传文件过大问题

问题背景 使用插件上传高清图片,用的插件base64转码的,上传失败,接口提示:413 (Request Entity Too Large) 问题分析与解决  首先想到的是nginx和php的服务器配 ...

饮冰三年-人工智能-Python-19 Python网络编程

Socket:套接字.作用:我们只需要安照socket的规定去编程,就不需要深入理解tcp/udp协议也可以实现 1:TCP协议 1.1  客户端服务端循环收发消息 # 1:引入stock模块(导包) ...

简述TCP三次握手和四次挥手过程

TCP握手协议 在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接.第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确 ...

c语言 int大端转小端,C++将整型数据转换成大端或小端存储顺序相关推荐

  1. [小技巧][JAVA][转换]整型int与字符char相互转换

    借助String.valueOf()过渡 char -> String ->int char c; String str = String.valueOf(c); int i = Inte ...

  2. [小技巧][JAVA][转换]整型int与字符串String相互转换

    字符串转换整型String - >Int 1). int i = Integer.parseInt([String]); 或者 //radix 进制 int i = Integer.parseI ...

  3. C语言操作符详解 隐式类型转换 (整型提升 算数转换)

    目录 一.算术操作符 二.左移操作符 右移操作符 1.二进制序列 2.左移操作符 3.右移操作符 3.1.逻辑运算/算术运算 3.2.对于移位运算符,不要移动负数位,这是标准未定义的 3.3.对于移位 ...

  4. 【最新】国际绝对音名标准频率及音符长度C语言宏定义(32位无符号整型精度、十二等律体系、A4=440.00000Hz)

    [最新]国际绝对音名标准频率及音符长度C语言宏定义(32位无符号整型精度.十二等律体系.A4=440.00000Hz) #ifndef __MUSIC_NOTE_H__ #define __MUSIC ...

  5. 基于Python的国际绝对音名标准频率C语言宏定义(32位无符号整型精度、十二等律体系、A4=440.01000Hz)

    基于Python的国际绝对音名标准频率C语言宏定义(32位无符号整型精度.十二等律体系.A4=440.01000Hz) 代码如下: f = open('./PITCH.h', 'w') C=44001 ...

  6. R语言dataframe数据列格式转换(从整型integer转化为浮点型float)

    R语言dataframe数据列格式转换(从整型integer转化为浮点型float) 目录 R语言dataframe数据列格式转换(从整型integer转化为浮点型float)

  7. C 语言格式输出 %hd,%hu分别是 短整型 和 无符号的短整型。

    C 语言格式输出 %hd,%hu分别是 短整型 和 无符号的短整型. %hd,%hu分别是 短整型 和 无符号的短整型. posted on 2011-08-22 20:29 雨亭 阅读( ...) ...

  8. java 把char转换成int型,java如何把char型数据转换成int型数据(转)

    一字符串,String="2324234535": 把第i个数取出来时是char型的:char temp=String.charAt(i) 如何把char型转换成int型? 我需要 ...

  9. C语言-输入任意多个数字,存到整型数组,支持任意间隔符,同时支持输入字母存到字符数组中

    第一次在CSDN上写博客- 记录一下想了有那么久的,这串代码 起因是做应用密码学的作业时,有Vigenere密码的加密解密.仿射密码加密解密.Playfair算法.Hill密码 因为数据量比较大,要把 ...

最新文章

  1. JavaScript实现轮播图
  2. APT: Package ‘vnc4server‘ has no installation candidate 排查过程及解决方法
  3. Qt安装vsaddin插件失败解决方案(vs、Qt、 vsaddin插件下载地址)
  4. 谷歌浏览器不能上网_谷歌浏览器插件下载及安装教程!
  5. xadmin 显示外键字段
  6. 避开使用XAML的性能陷阱
  7. jquery判断自己是父节点的第几个子节点
  8. 触发器中的 Inserted表和Deleted表
  9. 遗传算法 python_Python实现入门级遗传算法
  10. 2022年4月最新面经答案总结(Java基础、数据库、JVM、计网、计操、集合、多线程、Spring)持续更新
  11. 调试Python代码
  12. 计算机那个是固态硬盘,固态硬盘的好处是什么?电脑使用固态硬盘有什么用
  13. vue中使用(瀑布流)vue-waterfall-easy插件
  14. xynuoj 1919 三国志
  15. 代码详解设计模式--中介者模式
  16. ACWING297. 赤壁之战(树状数组dp)
  17. 51单片机实现简易闹钟(包含闹钟功能)
  18. 电脑与手机文件互传机制
  19. VMware如何监测性能问题
  20. ORACLE删除归档日志和ORA-00257问题

热门文章

  1. linux 16.04桌面系统,ubuntu16.04 server 安装经典桌面环境 Gnome 桌面
  2. JBL CM102 有源监听音箱使用体验
  3. html语言搭建网站,网络编程(1)——使用HTML搭建一个网页
  4. 谷歌浏览器html视频自动播放
  5. Attributed String学习笔记
  6. 第364章_显化一万年_神墓_辰东_玄幻小说
  7. 基因卡方列联表P值检验——相关系数图形
  8. 解决方案-joint_state_publisher process has died
  9. 百度前端技术学院:第三十一到第三十三天:我是精明的小卖家(一)
  10. 音频转码(MP3、PCM、G723.1)