1

私はエンディアンに取り組んでいます。私のリトルエンディアンプログラムは機能し、正しい出力を提供します。しかし、私はビッグエンディアンを回避することができません。以下は私がこれまでに持っているものです。私はビットシフトを使用する必要があることを知っています、そして私はそれで良い仕事をしているとは思いません。TAと教授に聞いてみましたが、あまり役に立ちません。私はこのリンクをたどっています(Cでビッグエンディアンをリトルエンディアンに変換します[提供された関数を使用せずに])。お手伝いありがとう。

#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

私はあなたに答えを与えるのではなく、あなたがそれを自分で解決するのを助けるために答えています。

まず、これを自問してください。1バイトに何ビットありますか?(ヒント:8)次に、?には何バイトありintますか?(ヒント:おそらく4)メモリ内のこの32ビット整数を想像してください:

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

次に、リトルエンディアンのマシンでバイト単位でそれを想像します。次のようになります。

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

バイトを正しい場所に配置するには、どのようなシフト操作が必要ですか?

のようなビット演算子を使用する場合は、ビットを操作していることを忘れない>>ください。したがって、整数値はプロセッサの反対のエンディアンに変換されます。1 << 241

于 2013-03-27T01:07:59.710 に答える
2

「リトルエンディアン」と「ビッグエンディアン」は、バイナリ表現でのバイトの順序(ここでは8ビットと見なすことができます)を指します。マシンを参照する場合、それはメモリ内のバイトの順序に関するものです。ビッグエンディアンのマシンでは、のアドレスはint最上位のバイトを指し、リトルエンディアンのマシンでは、のアドレスはint最下位のバイトを指します。 -オーダーバイト。

ただし、バイナリファイル(またはパイプや伝送プロトコルなど)を参照する場合は、ファイル内のバイトの順序を参照します。「リトルエンディアン表現」は、最下位バイトが最初で、最上位バイトが最初になります。過去。

?の最下位バイトを取得するにはどうすればよいintですか?これは下位8ビットなので、(n & 0xFF)(または((n >> 0) & 0xFF)、以下に示す有用性)です。

次の最下位バイトは((n >> 8) & 0xFF)です。次の最下位バイトは((n >> 16) & 0xFF)...または(((n >> 8) >> 8) & 0xFF)。等々。

したがってn、ループ内からバイトをはがして、一度に1バイトずつ出力することができます...そのために使用できますが、またはfwriteを使用する方が簡単です。putcharputc

あなたはあなたの先生があなたにを使うように要求すると言いますfwrite。これを行うには2つの方法があります:1)fwrite(&n, 1, 1, filePtr)上記のようにループで使用します。2)ループを使用してint、バイトをchar出力するのではなく、目的の順序で配列に格納して値を並べ替えてから、を使用して値fwriteを書き出します。後者はおそらくあなたの先生が念頭に置いていることです。

fwrite出力に使用するだけで機能することに注意してくださいint...リトルエンディアンのマシンで実行している場合int、のバイトはすでに正しい順序で格納されています。ただし、ビッグエンディアンマシンで実行している場合、バイトは逆方向になります。

于 2013-03-27T01:35:22.793 に答える
1

この質問に対するほとんどの回答の問題は、移植性です。私はここで移植可能な答えを提供しましたが、これは比較的わずかな正のフィードバックを受け取りました。Cは、未定義動作を次のように定義していることに注意してください。移植不可能または誤ったプログラム構成または誤ったデータを使用した場合の動作。この国際規格では要件はありません。

intここで説明する答えは、幅が16ビットであるとは想定していません。「より大きいint」値を表す方法がわかります。これは同じ概念ですが、2つではなく動的ループを使用しますfputc

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ではなく0からに移動sizeof intします。

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 に答える