我正在做作业关于位运算符,我不能做出正面或反面就可以了,我想我已经相当挂了字节序.也就是说,我正在使用一个小端机器(像大多数人一样),但是这需要考虑还是浪费的事实?
如果重要,我正在使用C.
根据我的理解,字节顺序是组成多字节字的字节顺序不同,至少在最典型的情况下.这样一个16位整数可以存储为0xHHLL
或者0xLLHH
.
假设我没有那个错误,我想知道的是,当Endian可能会或可能没有不同的两台计算机之间发送信息时,Endianness何时成为主要因素.
如果我以char数组的形式传输1的短整数并且没有校正,它是否被接收并解释为256?
如果我使用以下代码分解并重新组合短整数,那么字节序不再是一个因素吗?
// Sender:
for(n=0, n < sizeof(uint16)*8; ++n) {
stl_bitset[n] = (value >> n) & 1;
};
// Receiver:
for(n=0, n < sizeof(uint16)*8; ++n) {
value |= uint16(stl_bitset[n] & 1) << n;
};
Run Code Online (Sandbox Code Playgroud)提前致谢!
在允许我们通过UDP/IP控制它的硬件文档中,我发现了以下片段:
在这种通信协议中,DWORD是4字节数据,WORD是2字节数据,BYTE是单字节数据.存储格式为小端,即4字节(32位)数据存储为:d7-d0,d15-d8,d23-d16,d31-d24; 双字节(16位)数据存储为:d7-d0,d15-d8.
我想知道这是如何转换为C#的?在发送之前我是否必须转换内容?例如,如果我想发送32位整数或4个字符的字符串?
Big Endian和Little Endian Byte命令有什么区别?
这两者似乎都与Unicode和UTF16有关.我们到底在哪里使用它?
我正在研究memcache协议的实现,在某些点上,它使用64位整数值.这些值必须以"网络字节顺序"存储.
我希望有一些uint64_t htonll(uint64_t value)
功能可以进行更改,但不幸的是,如果它存在,我找不到它.
所以我有1或2个问题:
我想到了一个基本的实现,但我不知道如何在编译时检查字节序以使代码可移植.所以你的帮助非常受欢迎;)
谢谢.
这是我写的最终解决方案,感谢Brian的解决方案.
uint64_t htonll(uint64_t value)
{
// The answer is 42
static const int num = 42;
// Check the endianness
if (*reinterpret_cast<const char*>(&num) == num)
{
const uint32_t high_part = htonl(static_cast<uint32_t>(value >> 32));
const uint32_t low_part = htonl(static_cast<uint32_t>(value & 0xFFFFFFFFLL));
return (static_cast<uint64_t>(low_part) << 32) | high_part;
} else
{
return value;
}
}
Run Code Online (Sandbox Code Playgroud) 可能重复:
C宏定义确定大端或小端机器?
int main()
{
int x = 1;
char *y = (char*)&x;
printf("%c\n",*y+48);
}
Run Code Online (Sandbox Code Playgroud)
如果它是小端,它将打印1.如果它是大端,它将打印0.这是正确的吗?或者将char*设置为int x始终指向最低有效位,而不管字节顺序如何?
手册页htonl()
似乎暗示您只能将其用于最多32位值.(实际上,ntohl()
定义为无符号长整数,在我的平台上是32位.我想如果无符号长整数是8个字节,它将适用于64位整数).
我的问题是我需要将64位整数(在我的例子中,这是一个无符号长long)从big endian转换为little endian.现在,我需要进行特定的转换.但ntohl()
如果目标平台WAS大端,如果函数(如)不会转换我的64位值,它会更好.(我宁愿避免添加我自己的预处理器魔法来做到这一点).
我可以用什么?如果它存在,我想要标准的东西,但我愿意接受实施建议.我在过去使用过工会看过这种类型的转换.我想我可以拥有一个带有unsigned long long和char [8]的联合.然后相应地交换字节.(显然会在大端的平台上破解).
是否有一种安全,可移植的方法来确定(在编译期间)我的程序正在编译的平台的字节顺序?我在用C写作
[编辑]感谢您的回答,我决定坚持运行时解决方案!
我正在使用WebGL渲染二进制编码的网格文件.二进制文件以big-endian格式写出(我可以通过在十六进制编辑器中打开文件或使用fiddler查看网络流量来验证这一点).当我尝试使用Float32Array或Int32Array读取二进制响应时,二进制文件被解释为little-endian并且我的值是错误的:
// Interpret first 32bits in buffer as an int
var wrongValue = new Int32Array(binaryArrayBuffer)[0];
Run Code Online (Sandbox Code Playgroud)
我在http://www.khronos.org/registry/typedarray/specs/latest/找不到任何类型数组默认字节序的引用,所以我想知道这笔交易是什么?在使用类型化数组进行读取时,我是否应该假设所有二进制数据都应该是小端?
为了解决这个问题,我可以使用DataView对象(在上一个链接中讨论)并调用:
// Interpret first 32bits in buffer as an int
var correctValue = new DataView(binaryArrayBuffer).getInt32(0);
Run Code Online (Sandbox Code Playgroud)
默认情况下,"getInt32"等DataView函数会读取big-endian值.
(注意:我已经使用Google Chrome 15和Firefox 8进行了测试,它们的行为方式相同)
(我想这个问题可能适用于许多类型语言,但我选择使用C++作为例子.)
为什么没有办法写:
struct foo {
little int x; // little-endian
big long int y; // big-endian
short z; // native endianness
};
Run Code Online (Sandbox Code Playgroud)
指定特定成员,变量和参数的字节顺序?
我知道变量的类型不仅决定了用于存储值的字节数,还决定了在执行计算时如何解释这些字节.
例如,这两个声明每个都分配一个字节,对于两个字节,每个可能的8位序列都是有效值:
signed char s;
unsigned char u;
Run Code Online (Sandbox Code Playgroud)
但是相同的二进制序列可能会有不同的解释,例如11111111
,在分配时指的是-1,而指定时指的是s
255 u
.当有符号和无符号变量涉及相同的计算时,编译器(主要)负责正确的转换.
在我的理解中,字节序只是同一原则的变体:基于关于存储它的存储器的编译时信息对二进制模式的不同解释.
在允许低级编程的类型语言中使用该功能似乎是显而易见的.但是,这不是C,C++或我所知的任何其他语言的一部分,我没有在网上找到任何关于此的讨论.
我会试着总结一下我在询问后的第一个小时内收到的许多评论中的一些内容:
此外,现在我意识到签名和字节序不是一个完美的类比,因为:
big int
并little int
会具有完全相同的数值范围.unsigned char
(假设char
有8位)130不能用a表示signed …
endianness ×10
c++ ×4
c ×3
64-bit ×2
arraybuffer ×1
bit-shift ×1
byte ×1
c# ×1
hardware ×1
htonl ×1
javascript ×1
linux ×1
networking ×1
portability ×1
stl ×1
typed-arrays ×1
udp ×1
unicode ×1
utf-16 ×1
webgl ×1