1

我正在研究字节序。我的小端程序有效,并给出了正确的输出。但我无法绕过大端。以下是我到目前为止所拥有的。我知道我必须使用位移,但我认为我做得不好。我试着问我的助教和教授,但他们没有多大帮助。我一直在关注这个链接(在 C 中将 big endian 转换为 little endian [不使用提供的 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;
}   
4

3 回答 3

7

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

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

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

现在在一个 little-endian 机器上按字节想象它。它看起来像这样:

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

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

请记住,当您使用类似的位运算符时>>,您是在对进行操作。整1 << 24数值也将1转换为处理器的相反字节序。

于 2013-03-27T01:07:59.710 回答
2

“little-endian”和“big-endian”指的是二进制表示中的字节顺序(我们可以在这里假设 8 位)。当提到机器时,它与内存中字节的顺序有关:在大端机器上,an 的地址int将指向它的最高字节,而在小端机器上,an 的地址int将指向它的最低字节-顺序字节。

然而,当提到二进制文件(或管道或传输协议等)时,它指的是文件中字节的顺序:“小端表示”将首先具有最低位字节和最高位字节最后的。

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

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

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

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

请注意,如果你只是fwrite用来输出你的int它将工作......如果你在一个小端机器上运行,其中的字节int已经以正确的顺序存储。但是如果在大端机器上运行,字节会倒退。

于 2013-03-27T01:35:22.793 回答
1

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

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

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

将符号和绝对值分开。

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

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

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);

可移植方法更有意义,因为它们定义明确。

于 2013-03-27T02:23:24.327 回答