C 如何对整数的字节重新排序?

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

我的任务是使用C将数据文件从big-endian转换为little-endian,反之亦然。我已经在网上查找了大约3个小时的其他示例,并阅读了我的课本,但我仍然无法确定如何启动这个函数

到目前为止,我的事件顺序是正确的(1到4),但是在我的
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的答案,你会发现字节必须朝两个方向移动才能完成任务。