使用Bitshift运算符将little endian转换为big endian

时间:2013-03-27 00:58:13

标签: c

我正致力于结束。我的小端程序工作,并给出正确的输出。但我无法绕过大端。以下是我到目前为止所拥有的内容。 我知道我必须使用位移,我不认为我做得很好。我试过询问我的TA和教授,但他们帮助不大。 我一直在关注此链接(convert big endian to little endian in C [without using provided func])以了解更多信息,但仍无法使其正常运行。谢谢你的帮助。

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    FILE* input;
    FILE* output;

    input = fopen(argv[1],"r");
    output = fopen(argv[2],"w");
    int value,value2;
    int i;
    int zipcode, population;
    while(fscanf(input,"%d %d\n",&zipcode, &population)!= EOF)
    {
        for(i = 0; i<4; i++)
        {
        population = ((population >> 4)|(population << 4));
        }
        fwrite(&population, sizeof(int), 1, output);
    }

    fclose(input);      
    fclose(output);

    return 0;
}   

3 个答案:

答案 0 :(得分:7)

我回答的不是给你答案,而是帮你自己解决。

首先问问自己:一个字节中有多少位? (提示:8)接下来,int中有多少字节? (提示:可能是4)在内存中描绘这个32位整数:

  +--------+
0x|12345678|
  +--------+

现在用字节方式在小端机上拍照。它看起来像这样:

  +--+--+--+--+
0x|78|56|34|12|
  +--+--+--+--+

将字节放入正确的位置需要哪些移位操作?

请记住,当您使用>>之类的按位运算符时,您正在上运行。所以1 << 24将是整数值1转换为处理器的相反字节序。

答案 1 :(得分:2)

“little-endian”和“big-endian”是指二进制表示中的字节顺序(我们可以假定这里是8位)。在引用机器时,它是关于内存中字节的顺序:在大端机器上,int的地址将指向其最高位字节,而在小端机器上则指向一个地址。 int将引用其最低位字节。

当引用二进制文件(或管道或传输协议等)时,它指的是文件中字节的顺序:“little-endian表示”将首先具有最低位字节且最高-order byte last。

如何获得int的最低位字节?这是低8位,所以它是(n & 0xFF)(或((n >> 0) & 0xFF),您将在下面看到它的用处。)

下一个最低位字节是((n >> 8) & 0xFF)。 下一个最低位字节是((n >> 16) & 0xFF) ...或(((n >> 8) >> 8) & 0xFF)。 等等。

因此,您可以在循环中从n中删除字节并一次输出一个字节...您可以使用fwrite,但只使用putchar更简单或putc

您说您的老师要求您使用fwrite。有两种方法可以做到这一点:1)如上所述在循环中使用fwrite(&n, 1, 1, filePtr)。 2)使用循环通过在int数组中以所需顺序存储字节而不是输出它们来重新排序char值,然后使用fwrite将其写出来。后者可能是你老师的想法。

请注意,如果您只是使用fwrite输出int它将有效... 如果您正在小端机器上运行,那么int的字节已按正确顺序存储。但是如果在big-endian机器上运行,那么字节将会倒退。

答案 2 :(得分:1)

这个问题的大多数答案的问题是可移植性。我提供了一个可移植的答案here,但收到了相对较少的积极反馈。请注意,C将未定义的行为定义为:使用不可移植或错误的程序构造时的行为或错误数据,本国际标准不对其施加任何要求。

我在这里给出的答案不会假设int的宽度为16位;它会让你了解如何表示“更大的int”值。它是相同的概念,但使用动态循环而不是两个fputc

声明一个sizeof int无符号字符数组:unsigned char big_endian[sizeof int];

分隔符号和绝对值。

int sign = value < 0;
value = sign ? -value : value;

sizeof int循环到0,写入最低有效字节:

size_t foo = sizeof int;
do {
    big_endian[--foo] = value % (UCHAR_MAX + 1);
    value /= (UCHAR_MAX + 1);
} while (foo > 0);

现在插入标志:foo[0] |= sign << (CHAR_BIT - 1);

简单,是吗?小端也同样简单。只需颠倒循环的顺序,从0到sizeof int,而不是从sizeof int到0:

size_t foo = 0;
do {
    big_endian[foo++] = value % (UCHAR_MAX + 1);
    value /= (UCHAR_MAX + 1);
} while (foo < sizeof int);

便携式方法更有意义,因为它们定义得很好。