2

今日、私はchar **オブジェクトがメモリまたはバイナリ ファイルにどのように保存されるかを尋ねました。次のコード スニペットでテストしました。

char **array  = (char *)malloc(3 * sizeof(char *));

array[0] = "Foo";         // Length: 3
array[1] = "Long string"; // Length: 11
array[2] = "Bar";         // Length: 3   => Full length: 17

int length = 17;

この配列をファイルに書き込みます。

FILE *file = fopen(...);
fwrite(array, length, 1, file);
fclose(file);

すばらしいことに、次のコードを使用してファイルからこの配列を再度読み取ると、17 バイト以上を保存することなく、文字列の長さが正常に読み取られます。

FILE *file   = fopen(...);
int   length = 17;

char **array = (char *)malloc(length);

int index        = 0;
int parsedLength = 0;
while (parsedLength < length)
{
    char *string       = array[index];
    int   stringLength = strlen(string);

    printf("%i: \"%s\" (%i)\n", index, string, stringLength);

    parsedLength += stringLength;
    ++index;
}

次のような出力が得られます。

0: "Foo" (3)
1: "Long string" (11)
2: "Bar" (3)

コンパイラは、配列内の各文字列の長さをどのように認識しますか?

4

2 に答える 2

13

ポインターは数字 (またはより適切なアドレス) のようにファイルに保存されるため、コードが機能するという事実は、おそらく同じ実行で同じプログラム内で保存およびロードしているという事実によって作成された錯覚です (したがって、これらの文字列はリテラルであるため) 、それらのアドレスはほとんどデータセグメントで固定されています)。

メモリ内の配列のレイアウトは次のとおりであるため、あなたがしていることは完全に間違っています(4バイトのポインターを想定しています):

XXXXXXXX YYYYYYYY ZZZZZZZZ ( = 12 bytes)
   ^        ^        ^
   |        |       pointer to "Bar"
   |      pointer to "Long String"
 pointer to "Foo"

しかし、ファイルに 17 バイトを保存しています。そのうちの 12 バイトは単なるメモリ アドレスです。

文字列をファイルに正しく保存するには、含まれているデータ全体とその長さを確実に保存する必要があります。何かのようなもの:

for (int i = 0; i < ARRAY_LENGTH; ++i) {
  char *string = array[i];
  unsigned int length = strlen(string);
  fwrite(&length, sizeof(unsigned int), 1, out);
  fwrite(string, sizeof(char), length, out);
}

for (int i = 0; i < ARRAY_LENGTH; ++i {
  unsigned int length;
  fread(&length, sizeof(unsigned int), 1, in);
  array[i] = calloc(sizeof(char), length);
  fread(array[i], sizeof(char), length, in);
}
于 2013-05-14T19:41:27.940 に答える
3

プログラムが機能するとは思わないでください。ファイルを読み取る新しいプログラムを作成するか、バイナリ ファイルを 16 進エディタで開いてみてください。文字列は存在しません。 char ** arraychar の配列ではなくポインターの配列であり、そのサイズは 32 ビット共通環境では 3*4 = 12 です。

于 2013-05-14T19:42:23.537 に答える