2

私は現在、いくつかの文字列を含むいくつかの任意の値、およびuint32_t'sとして格納される文字列の長さの値のバイナリファイル形式に取り組んでいます。

しかし、リトルエンディアンシステムのファイルに文字列の長さを書き込み、ビッグエンディアンシステムfwriteの同じファイルからその値を読み取るとfread、バイトの順序が逆になりますか?もしそうなら、それを修正するためのベストプラクティスは何ですか?

編集:確かに、私のためにこれを行ういくつかのGNU機能が必要であり、それは20年間使用され、テストされ、検証されていますか?

4

4 に答える 4

3

リトルエンディアンシステムのファイルにfwriteを使用して文字列の長さを書き込み、ビッグエンディアンシステムのfreadを使用して同じファイルからその値を読み取ると、バイトの順序が逆になりますか?

はい。 fwriteメモリの内容を線形順にファイルに書き込むだけです。 freadファイルからメモリに線形順序で読み取るだけです。

それを修正するためのベストプラクティスは何ですか?

ファイルの順序を決定します。次に、ラッパー関数を記述して、ファイルとの間で整数を読み書きします。この関数内で、逆の順序のシステムを使用している場合は、条件付きでバイト順序を反転します。

(システムのエンディアンの決定に関して、ここには多くの質問があります。)

確かに、私のためにこれを行ういくつかのGNU機能が必要です

標準ライブラリには何もありません。ただし、POSIXは、このための一連の関数を定義しています:ntohl、、htonlなど。これらは通常、ネットワーク転送に使用されますが、ファイルにも同様に使用できます。

于 2013-02-09T20:41:33.437 に答える
3

はい、そうなります。戦争の生のバイトでfread()動作するからです。メモリ内でバイトの順序が異なる場合、ファイル内でも異なります。

もしそうなら、それを修正するためのベストプラクティスは何ですか?

システムのエンディアンを検出し、ファイル形式のエンディアンと一致しない場合はバイトを反転します。

int is_little_endian()
{
    uint32_t magic = 0x00000001;
    uint8_t black_magic = *(uint8_t *)&magic;
    return black_magic;
}

uint32_t to_little_endian(uint32_t dword)
{
    if (is_little_endian()) return dword;

    return (((dword >>  0) & 0xff) << 24)
         | (((dword >>  8) & 0xff) << 16)
         | (((dword >> 16) & 0xff) <<  8)
         | (((dword >> 24) & 0xff) <<  0);
}
于 2013-02-09T20:42:51.517 に答える
3

はい。整数の場合fwritefread他の回答が正しく述べているように、ファイル形式を別のエンディアンに移植できなくなります。

ベストプラクティスとして、条件付きバイトフリッピングとエンディアンネステストは一切お勧めしませんバイトの書き込みと読み取りではなく、ファイル形式のエンディアンを決定し、ORとシフトによってそれらから整数を作成します。

言い換えれば、私はこの問題についてロブ・パイクに同意します。

于 2013-02-09T21:00:49.060 に答える
1

Linuxは提供します

htobe16、htole16、be16toh、le16toh、htobe32、htole32、be32toh、le32toh、htobe64、htole64、be64toh、le64toh-ホストとビッグ/リトルエンディアンのバイト順序の間で値を変換します

[ https://linux.die.net/man/3/le32toh]

于 2017-10-12T15:27:04.983 に答える