C语言 如何保存char **对象



今天,我问我,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字节指针):

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);
}

我认为你的程序不起作用。试着写一个新的程序来读取你的文件,或者试着用十六进制编辑器打开二进制文件。字符串不存在于其中。char ** array是指针数组而不是char数组,其大小为3*4 = 12,在32位通用环境下

最新更新