3

Cを使用して構造体をファイルに「パック」および「書き込み」するには、次のようにするにはどうすればよいですか。

構造体{
    uint64_t a;
    char * b;
    uint16_t c;
} a;
ab;
ba = 3;
bb="こんにちは";
bc = 4;

次のようにファイルに書き込まれます

00 00 00 00 00 00 00 03 48 65 6c 6c 6f 00 00 04
4

4 に答える 4

9

Cでは、これを行うための関数をコーディングする必要があります。bはバッキング文字列なしでは意味をなさないポインタであるため、構造をディスクに単純化することはできません。また、コンパイラがその構造をどのようにパックするかを知っている(そして制御できる)場合を除いて、ポインタがなくても、とにかくユーティリティ関数を使用する方がよいでしょう。

そして、それだけでは不十分であるかのように、文字列の長さも出力して、読み戻すバイト数がわかるようにする必要があります。

次のようなものを探します。

int better_than_blat (FILE *f, struct a *x) {
    size_t len = strlen (x->b);
    if (fwrite (&(x->a), sizeof(long), 1, f) != 1) return -1;
    if (fwrite (&len, sizeof(size_t), 1, f) != 1) return -1;
    if (fwrite (x->b, len, 1, f) != 1) return -1;
    if (fwrite (&(x->c), sizeof(short), 1, f) != 1) return -1;
    return 0;
}

int better_than_unblat (FILE *f, struct a *x) {
    size_t len;
    if (fread (&(x->a), sizeof(long), 1, f) != 1) return -1;
    if (fread (&len, sizeof(size_t), 1, f) != 1) return -1;
    x->b = malloc (len + 1);
    if (x->b == NULL) return -1;
    memset (x->b, 0, len + 1);
    if (fread (x->b, len, 1, f) != 1) return -1;
    if (fread (&(x->c), sizeof(short), 1, f) != 1) return -1;
    return 0;
}
于 2010-08-11T08:55:19.007 に答える
2

このデータをシリアル化する独自の方法を作成する必要があります。コンパイラは、文字列を処理するための組み込みの方法を提供しません。そこにはシリアル化ライブラリがありますが、ストレートCについてはわかりません。

ただし、jsonやxmlなど、データをシリアル化するためのより構造化された方法を使用することを検討してください。INIファイルでさえ生のバイナリダンプよりも優れています。この理由は次のとおりです。

  • デバッグが簡単
  • より上位互換性
  • 剛性が低い/エラーが発生しやすい
  • 既存のライブラリを使用する場合は、それに伴うコミュニティの報酬を享受できます。
  • 既存のライブラリは、後で配列のように頭を悩ませる機能をサポートしている可能性があります
  • クロスプラットフォームの互換性が向上します。
于 2010-08-11T08:55:18.707 に答える
0

以下は役に立ちますか?

struct buffer {

  char bytes[1000];
  int nbytes;
};

struct buffer *new_buffer(){
  struct buffer b = (struct buffer*) malloc(sizeof(struct buffer));
  b->nbytes = 0;
  return b;
}

void append_long(struct buffer *b, long *l){
  memcpy(b->bytes + b->nbytes, l);
  b->nbytes += sizeof(*l);
}

// ...and so on for other types

void fwrite_buffer(FILE *fp, struct buffer *b){
  fwrite(b->bytes, sizeof(*b), 1, fp);
}

使用法:

struct buffer *buf = new_buffer();
struct a b;
b.a = 3;
b.b = "Hello";
b.c = 4;
append_long(buf, &(b.a));
append_pointer(buf, &(b.b));
append_short(buf, &(b.b));
fwrite_buffer(fp, buf);
于 2010-08-11T08:59:28.980 に答える
0

構造体でポインターを使用せず、パッキング アラインメントを明示的に定義する場合は、構造体をバイト配列に安全にパックできます。

例 (gcc):

{ を構築する
    長い;
    char b[256];
    短いc;
} __attribute__((__packed__));

int size = sizeof(a);
void* バッファ = malloc(サイズ);
memcpy(バッファ、(void*)a、サイズ);
于 2010-08-11T09:12:40.650 に答える