我正致力于结束。我的小端程序工作,并给出正确的输出。但我无法绕过大端。以下是我到目前为止所拥有的内容。 我知道我必须使用位移,我不认为我做得很好。我试过询问我的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;
}
答案 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);
便携式方法更有意义,因为它们定义得很好。