C 如何对整数的字节重新排序?
我的任务是使用C将数据文件从big-endian转换为little-endian,反之亦然。我已经在网上查找了大约3个小时的其他示例,并阅读了我的课本,但我仍然无法确定如何启动这个函数 到目前为止,我的事件顺序是正确的(1到4),但是在我的C 如何对整数的字节重新排序?,c,endianness,converters,C,Endianness,Converters,我的任务是使用C将数据文件从big-endian转换为little-endian,反之亦然。我已经在网上查找了大约3个小时的其他示例,并阅读了我的课本,但我仍然无法确定如何启动这个函数 到目前为止,我的事件顺序是正确的(1到4),但是在我的convert\u和\u save函数中,我必须使用→ 字符缓冲区[4] 有人能帮我吗?即使你能给我一些线索,告诉我该查什么,我也会非常感激 我需要编写一个函数,名为: void convert_and_save(struct record item, FIL
convert\u和\u save
函数中,我必须使用→ <代码>字符缓冲区[4]代码>
有人能帮我吗?即使你能给我一些线索,告诉我该查什么,我也会非常感激
我需要编写一个函数,名为:
void convert_and_save(struct record item, FILE * output_handle, int number);
在该函数中,我执行以下一系列步骤:
int integer_to_characters(int number, char * buffer)
{
memcpy(buffer, &number, 4);
}
int characters_to_integer(char * buffer)
{
int result;
memcpy(&result, buffer, 4);
return result;
}
void save_record(FILE * file_handle, struct record a)
{
char output_buffer[size_of_record];
integer_to_characters(a.age, &(output_buffer[0]));
memcpy(&(output_buffer[4]), a.name, 12);
integer_to_characters(a.department, &(output_buffer[16]));
fwrite(output_buffer, sizeof(char), size_of_record, file_handle);
}
您可能想看看,其中显示了如何使用不同的字节大小进行双向转换。 这是一种方法,但更有效的方法将在线程链接中讨论
uint32_t num = 9;
uint32_t b0,b1,b2,b3,b4,b5,b6,b7;
uint32_t res = 0;
b0 = (num & 0xf) << 28;
b1 = (num & 0xf0) << 24;
b2 = (num & 0xf00) << 20;
b3 = (num & 0xf000) << 16;
b4 = (num & 0xf0000) << 12;
b5 = (num & 0xf00000) << 8;
b6 = (num & 0xf000000) << 4;
b7 = (num & 0xf0000000) << 4;
res = b0 + b1 + b2 + b3 + b4 + b5 + b6 + b7;
printf("%d\n", res);
uint32\u t num=9;
uint32_t b0、b1、b2、b3、b4、b5、b6、b7;
uint32_t res=0;
b0=(num&0xf)这是我为Parrot VM编写的函数之一,您可以从parrotcode.org下载byteorder.c。可能有较短的方法,但这适用于不同大小的整数,我们有一个宏来检测PARROT_BIGENDIAN中平台的字节顺序,您可以放弃所有这些。此外,如上所述,您可以搜索htonl(),它是bigendian硬件上的nop,但在little-endian上转换(只需获取一个Linux x86实现)
INTVAL
取回(内部w)
{
断言参数(获取参数)
#如果!鹦鹉学舌
返回w;//在little endian硬件上没有操作
#否则
#如果INTVAL_SIZE==4
返回(w 8)|(w>>24);
#否则
#如果INTVAL_SIZE==8
INTVAL r;
r=w24;
r |=(w&0xff000000000000)>>40;
r |=(w&0xff00000000000000)>>56;
返回r;
#恩迪夫
#恩迪夫
#恩迪夫
}
这些不是标准函数(这些是gcc扩展),但您可以使用它们:
-内置函数:uint16\u t\u内置函数bswap16(uint16\u t x)返回x
字节顺序颠倒;例如,0xaabb变为
0xbbaa。这里的字节总是正好表示8位
-内置功能:uint32\u t\u内置bswap32(uint32\u t x)类似
到uuu builtin_bswap16,参数和返回类型为32位除外
-内置功能:uint64_t_内置bswap64(uint64_t x)类似
除了参数和返回类型为64位之外,其他都是内置的bswap32
如果您能使用这些,很可能会为您的平台生成更优化的代码,如果不能,请向gcc提交一个补丁:)
Clang还有\uuuuuuBuiltin\uBSWAP16()\uuuBuiltin\uBSWAP32()\uuuuBuiltin\uBSWAP64()
Visual Studio
unsigned short _byteswap_ushort (
unsigned short val
);
unsigned long _byteswap_ulong (
unsigned long val
);
unsigned __int64 _byteswap_uint64 (
unsigned __int64 val
);
ICC有bswap16、bswap和bswap64需要进一步参考这是我的样本。它反转整数的尾数。请注意,C没有指定int的大小。它可以是16、32、64。。。如果要确保尺寸,请改用(uint_16t、uint_32t、uint_64t)
void reverse_endianess(int* number)
{
char byte_arr[8] = {0};
int i;
for (i=0; i < sizeof(int); i++) {
byte_arr[i] = (*number & 0xFF);
*number = *number >> 8;
}
*number = 0;
for (i=0; i < sizeof(int); i++) {
*number |= byte_arr[i];
*number = *number << 8;
}
}
void reverse\u endianess(整数*数字)
{
字符字节_arr[8]={0};
int i;
对于(i=0;i>8;
}
*数字=0;
对于(i=0;i *number=*number看看这个答案:
如果使用的是Visual C++,请执行以下操作:包括intrin.h并调用以下函数:
对于16位数字:
unsigned short _byteswap_ushort(unsigned short value);
unsigned long _byteswap_ulong(unsigned long value);
unsigned __int64 _byteswap_uint64(unsigned __int64 value);
对于32位数字:
unsigned short _byteswap_ushort(unsigned short value);
unsigned long _byteswap_ulong(unsigned long value);
unsigned __int64 _byteswap_uint64(unsigned __int64 value);
对于64位数字:
unsigned short _byteswap_ushort(unsigned short value);
unsigned long _byteswap_ulong(unsigned long value);
unsigned __int64 _byteswap_uint64(unsigned __int64 value);
8位数字(字符)不需要转换
此外,它们仅为无符号值定义,也适用于有符号整数
对于浮点数和双精度浮点,与普通整数一样困难,因为它们可能在主机字节顺序中,也可能不在主机字节顺序中。在大端机器上可以得到小端浮点,反之亦然
其他编译器也有类似的内部函数
例如,在GCC中,您可以直接调用:
uint16_t __builtin_bswap16 (uint16_t x)
uint32_t __builtin_bswap32 (uint32_t x)
uint64_t __builtin_bswap64 (uint64_t x)
找到了吗?请记住,在主机顺序不同于网络字节顺序的平台上,htonl()是一个很好的例子,但在big-endian平台上,htonl()是一个noop/empty宏#define htonl(x)x,所以请务必查看Intel little-endian实现(典型的Linux)。它是“逆序”还是“从大端到小端的转换”?它们不是一回事i=((i&0xFF)8)|((i&0xFF000000)>>24);
您复制到此答案中的代码不正确。我建议您阅读链接的问题,包括所有注释。OP发布了此代码,但它不正确,并且在注释中指出了一些缺陷。当然,您不能移动所有字节(或半字节)如果你想颠倒顺序,就朝一个方向移动。轮班不是轮换。阅读@mrjoltcola的答案,你会发现字节必须朝两个方向移动才能完成任务。