可能重复:
在C++程序中以编程方式检测字节顺序
是否有任何库函数可用于查找我的PC的字节序?
我有一个非常简单的问题,这对我来说很难,因为这是我第一次尝试使用二进制文件,我不太了解它们.我想要做的就是将一个整数写入二进制文件.
我是这样做的:
#include <fstream>
using namespace std;
int main () {
int num=162;
ofstream file ("file.bin", ios::binary);
file.write ((char *)&num, sizeof(num));
file.close ();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果我做错了什么,你能告诉我什么?
给我带来麻烦的部分是与file.write一致,我不明白.
先感谢您.
今天早上我和一位同事讨论了关于检测字节序的"编码技巧"的正确性.
诀窍是:
bool is_big_endian()
{
union
{
int i;
char c[sizeof(int)];
} foo;
foo.i = 1;
return (foo.c[0] == 1);
}
Run Code Online (Sandbox Code Playgroud)
对我来说,似乎这种用法union
是不正确的,因为设置联合的一个成员并读取另一个成员的定义并不明确.但我必须承认,这只是一种感觉,我缺乏实际的证据来强化我的观点.
这个技巧是否正确?谁在这?
我必须实现一个定义8位字数据的协议,首先从最低有效位(LSB)开始.我想用这个数据来实现这个数据unsigned char
,但是我不知道在C/C++中LSB和最高有效位(MSB)的位顺序是什么,可能需要交换位.
任何人都可以解释我如何找出unsigned char
编码:MSB-LSB或LSB-MSB?
例:
unsigned char b = 1;
MSB-LSB: 0000 0001
LSB-MSB: 1000 0000
背景
在设计二进制文件格式时,通常建议以网络字节顺序写入整数.为此,有像宏一样的宏htonhl()
.但对于像WAV这样的格式,实际上使用的是小端格式.
题
无论您的代码运行的CPU是大端还是小端架构,您如何便携地编写小端值?(想法:可以使用标准宏ntohl()
并htonl()
以某种方式"反向"使用吗?或者代码只是测试运行时是否在小端或大端CPU上运行并选择适当的代码路径?)
所以问题不在于文件格式,文件格式只是一个例子.它可以是任何类型的序列化,其中需要"线上"的小端,例如(异端)网络协议.
请不要将此标记为重复.该建议后重复实际上是在说有关运行时决定.最重要的是,那里的答案都没有回答我的问题.
我需要uint16_t
用C/C++中的两个字节读取一个.所以,我需要决定我的代码编译的平台的endian格式.我目前在GNU C扩展中使用宏.
// 'size' is 'uint16_t' and read from big-endian format.
// So if the platform is little-endian, I need to flip the btyes.
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
size = ( size << 8 ) | ( size >> 8 );
#endif
Run Code Online (Sandbox Code Playgroud)
性能在我的用例中至关重要,因此ntohs
或htons
不适合我.我需要在预处理时间内进行这种endian检查.
题.是否有标准方法(语言标准)来进行预处理?
当你读取一大块字节并且需要将它们转换为数字时,node.js具有buffer.readInt32BE()
和的函数buffer.readInt32LE()
.
如果我只知道文件的前4个字节是整数,如果我不知道系统的字节顺序,我应该使用什么函数?大端还是小端?
做一个快速的谷歌搜索(stackoverflow),在C中我们可以测试字节序:
if ( htonl(47) == 47 ) {
// Big endian
} else {
// Little endian.
}
Run Code Online (Sandbox Code Playgroud)
我们如何在node.js中测试endianness以正确使用readInt32BE和readInt32Le?
我有一串256*4字节的数据.这些256*4字节需要转换为256个无符号整数.它们来的顺序是小端,即字符串中的前四个字节是第一个整数的小端表示,接下来的4个字节是下一个整数的小端表示,依此类推.
解析这些数据并将这些字节合并为无符号整数的最佳方法是什么?我知道我必须使用bitshift运算符,但我不知道以什么方式.
如何在编译时确定我的平台是小端还是大端?我已经看到很多方法可以在运行时使用强制转换来确定,以及一些与平台相关的选项.有便携式或标准方式吗?
constexpr bool is_little_endian = ?;
Run Code Online (Sandbox Code Playgroud) 我很惊讶 StackOverflow 上有这么多主题涉及找出系统的字节顺序和转换字节顺序。更令我惊讶的是,这两个问题有数百种不同的答案。到目前为止,我看到的所有建议的解决方案都是基于未定义的行为、非标准编译器扩展或特定于操作系统的头文件。在我看来,如果现有答案提供了符合标准、高效(例如,使用 x86- )、支持编译时间的解决方案,则这个问题只是重复的。bswap
当然,一定有一个符合标准的解决方案可用,但我无法在一大堆旧的“hacky”解决方案中找到它。还有一点奇怪的是,标准库中没有包含这样的函数。也许对此类问题的态度正在改变,因为 C++20 在标准中引入了一种检测字节顺序的方法(通过std::endian
),并且 C++23 可能会包含std::byteswap
,这会翻转字节顺序。
无论如何,我的问题是:
从什么 C++ 标准开始,是否有一种可移植的符合标准的方法来执行主机到网络字节顺序转换?
我在下面论证这在 C++20 中是可能的。我的代码正确吗?可以改进吗?
这样的纯 C++ 解决方案是否应该优先于操作系统特定功能(例如 POSIX-)htonl
?(我想是的)
我想我可以给出一个独立于操作系统、高效(无系统调用,使用 x86- )并且可移植到小端和大端系统(但不能移植到混合端系统)的C++23 解决方案:bswap
// requires C++23. see https://gcc.godbolt.org/z/6or1sEvKn
#include <type_traits>
#include <utility>
#include <bit>
constexpr inline auto host_to_net(std::integral auto i) {
static_assert(std::endian::native == std::endian::big || std::endian::native == std::endian::little);
if constexpr (std::endian::native == std::endian::big) {
return i;
} else {
return std::byteswap(i);
}
}
Run Code Online (Sandbox Code Playgroud)
由于std::endian
在 C++20 中可用,因此可以通过手动实现 …