当询问C中常见的未定义行为时,灵魂比我提到的严格别名规则更加开明.
他们在说什么?
我需要在C中编写一个将big endian转换为little endian的函数.我不能使用任何库函数.
鉴于此代码:
#include <string.h>
int equal4(const char* a, const char* b)
{
return memcmp(a, b, 4) == 0;
}
int less4(const char* a, const char* b)
{
return memcmp(a, b, 4) < 0;
}
Run Code Online (Sandbox Code Playgroud)
x86_64上的GCC 7引入了第一种情况的优化(Clang已经做了很长时间):
mov eax, DWORD PTR [rsi]
cmp DWORD PTR [rdi], eax
sete al
movzx eax, al
Run Code Online (Sandbox Code Playgroud)
但第二种情况仍然是memcmp():
sub rsp, 8
mov edx, 4
call memcmp
add rsp, 8
shr eax, 31
Run Code Online (Sandbox Code Playgroud)
是否可以对第二种情况应用类似的优化?什么是最好的装配,有没有明确的理由为什么它没有完成(由GCC或Clang)?
在Godbolt的Compiler Explorer上看到它:https://godbolt.org/g/jv8fcf
我做了一些谷歌搜索,在这个问题上找不到任何好文章.在实现我想要与endian无关的应用程序时,我应该注意什么?
我一直在寻找如何将big-endian转换为little-endians.但我找不到任何可以解决我问题的好处.似乎有很多方法可以进行这种转换.无论如何,以下代码在big-endian系统中正常工作.但是我应该如何编写转换函数,以便它也适用于little-endian系统?
这是一个功课,但它只是一个额外的,因为在学校运行大端系统的系统.这只是我很好奇,并希望它也可以在我的家用电脑上工作
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream file;
file.open("file.bin", ios::in | ios::binary);
if(!file)
cerr << "Not able to read" << endl;
else
{
cout << "Opened" << endl;
int i_var;
double d_var;
while(!file.eof())
{
file.read( reinterpret_cast<char*>(&i_var) , sizeof(int) );
file.read( reinterpret_cast<char*>(&d_var) , sizeof(double) );
cout << i_var << " " << d_var << endl;
}
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
解决了
所以Big-endian VS Little-endian只是字节的逆序.我写的这个功能似乎无论如何都符合我的目的.我在这里添加它以防万一其他人将来需要它.这只是双倍,但是对于整数,要么使用建议的函数torak,要么可以通过使它仅交换4个字节来修改此代码.
double swap(double d)
{
double a;
unsigned char *dst = (unsigned …Run Code Online (Sandbox Code Playgroud) 我有一个非常简单的问题,这对我来说很难,因为这是我第一次尝试使用二进制文件,我不太了解它们.我想要做的就是将一个整数写入二进制文件.
我是这样做的:
#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一致,我不明白.
先感谢您.
我正在编写一个ELF分析器,但我在转换字节顺序方面遇到了一些麻烦.我有函数来确定分析器的字节顺序和目标文件的endiannness.
基本上,有四种可能的情况:
是否有一个函数我可以用来显式交换字节顺序/更改字节顺序,因为ntohs/l()和htons/l()考虑了主机的字节序,有时不转换?或者我是否需要查找/编写自己的交换字节顺序功能?
给定一个需要解析的32位little-endian字段的二进制文件,我想编写正确编译的解析代码,而不依赖于执行该代码的机器的字节顺序.目前我用
uint32_t fromLittleEndian(const char* data){
return uint32_t(data[3]) << (CHAR_BIT*3) |
uint32_t(data[2]) << (CHAR_BIT*2) |
uint32_t(data[1]) << CHAR_BIT |
data[0];
}
Run Code Online (Sandbox Code Playgroud)
然而,这会产生不理想的装配.在我的机器上g++ -O3 -S产生:
_Z16fromLittleEndianPKc:
.LFB4:
.cfi_startproc
movsbl 3(%rdi), %eax
sall $24, %eax
movl %eax, %edx
movsbl 2(%rdi), %eax
sall $16, %eax
orl %edx, %eax
movsbl (%rdi), %edx
orl %edx, %eax
movsbl 1(%rdi), %edx
sall $8, %edx
orl %edx, %eax
ret
.cfi_endproc
Run Code Online (Sandbox Code Playgroud)
为什么会这样?在小端机器上编译时,我怎么能说服它生成最佳代码:
_Z17fromLittleEndian2PKc:
.LFB5:
.cfi_startproc
movl (%rdi), %eax
ret
.cfi_endproc
Run Code Online (Sandbox Code Playgroud)
我通过编译得到的:
uint32_t fromLittleEndian2(const char* data){
return …Run Code Online (Sandbox Code Playgroud) 我正在尝试为在Win XP上运行的C++程序编写一个byteswap例程.我正在使用Visual Studio 2008编译.这就是我想出的:
int byteswap(int v) // This is good
{
return _byteswap_ulong(v);
}
double byteswap(double v) // This doesn't work for some values
{
union { // This trick is first used in Quake2 source I believe :D
__int64 i;
double d;
} conv;
conv.d = v;
conv.i = _byteswap_uint64(conv.i);
return conv.d;
}
Run Code Online (Sandbox Code Playgroud)
还有一个测试功能:
void testit() {
double a, b, c;
CString str;
for (a = -100; a < 100; a += 0.01) {
b = byteswap(a);
c …Run Code Online (Sandbox Code Playgroud) 我已经下载了Dukascopy tick数据,我用easylzma库解压缩了它.原始压缩二进制文件是EURUSD/2010/00/08/12h_ticks.bi5(EURUSD/2010/ian/8/12h)解压后我们得到以下格式:
+-------------------------+--------+-------+
| time | Bid | Ask |
+-------------------------+--------+-------+
000003CA 00022EC0 00022EB6 40CCCCCD 41180000
000004F5 00022EB6 00022EB1 4099999A 404CCCCD
Run Code Online (Sandbox Code Playgroud)
(您可以从以下网址下载原始压缩文件: EURUSD/2010/00/08/12h_ticks.bi5.使用lzma解压缩后我们得到文件: 12h_ticks)
读取二进制文件:
int ii1;
int ii2;
int ii3;
float ff1;
float ff2;
ifstream in("12h_ticks",ofstream::binary);
in.read((char*)(&ii1), sizeof(int));
in.read((char*)(&ii2), sizeof(int));
in.read((char*)(&ii3), sizeof(int));
in.read((char*)(&ff1), sizeof(float));
in.read((char*)(&ff2), sizeof(float));
std::cout << " ii1=" << ii1 << std::endl;
std::cout << " ii2=" << ii2 << std::endl;
std::cout << " ii3=" << ii3 << std::endl;
std::cout << …Run Code Online (Sandbox Code Playgroud) c++ ×7
endianness ×6
c ×4
binary ×1
binaryfiles ×1
clang ×1
fstream ×1
gcc ×1
integer ×1
optimization ×1
swap ×1
type-punning ×1
x86-64 ×1