【问题标题】:Do I need to write pointers from structs individually to files?我是否需要将结构中的指针单独写入文件?
【发布时间】:2013-07-24 12:59:58
【问题描述】:

我正在尝试使用 C 进行编程。我认为重要的一个重要步骤是了解如何使用原始内存块,初始化它们并释放它们。 在手头的测试程序中,我创建了两个结构,每个结构都有一个指针。

struct Address {
    int id;
    int var;
    char *name;
};

struct Link {
    int link_var;
    struct Address *addr;
};

name 和 addr 在这种情况下是指针,因为我希望它们是动态大小的。

int main(int argc, char *argv[])
{    
    FILE *file = fopen("test.dat", "w");
    int i = 0;

    struct Link *link = malloc(sizeof(struct Link) + (sizeof(struct Address)*10) + (10*10));

    struct Address addr_container[10];

    for(i = 0; i < 10; i++) {

        char temp_name[10];
        memset(temp_name, '\0', 10);

        temp_name[0] = 'A';

        struct Address addr_proto = {.id = i, .var = 10, .name = temp_name};

        addr_container[i] = addr_proto;
    }

    struct Link link_proto = {.link_var = 2, .addr = addr_container};

    memcpy(link, &link_proto, sizeof(struct Link) + (sizeof(struct Address)*10) + (10*10));

    printf("%s\n", link->addr[4].name);



    int rc = fwrite(link, sizeof(struct Link) + (sizeof(struct Address)*10) + (10*10), 1, file);
    if(rc != 1) printf("Failed to write database.");

    fclose(file);
    free(link);

    return 0;
}

所以我在这里选择的方式是分配 *link 所需的所有内存。之后,我创建了一个链接结构的原型,其中所有数据都已初始化。 (结构中的指针也指向初始化值)

之后,我将堆栈内存中原型中的所有数据复制到堆上的原始内存块中。使用 memcpy。

当我写一个文件的链接时,Valgrind 对我大喊我要写未初始化的字节。

是因为我需要为结构中的所有指针单独分配内存吗?我不明白我如何编写一个包含我想要的所有链接和数据的文件。所以我可以阅读它并重新应用到一个新的空链接结构。

我是 C 的新手,这是学习内存分配的早期尝试,所以我很高兴看到每个批评我的代码的答案。我也确实在 stackoverflow 上搜索了答案,并找到了关于需要为结构中的指针分配内存的答案。但我无法弄清楚如何在代码中实现它。 我还阅读了有关制作一个循环的信息,该循环将代码写入结构中的文件以及我需要的链接。这是最有效和最单一的方法吗?

顺便说一句:我需要使用指针,因为最后我希望这些指针可以使字符和地址结构数组的大小不同。

【问题讨论】:

  • 在您的struct Address 中,id 字段很可能会中断,因为id 是Objective-C 中的保留关键字,它被定义为void *,IIRC。但是您尝试做的似乎是纯 C。
  • 全是 C。那个问题没有 Objective-C。
  • 那么 Objective-C 是从哪里来的呢?对我来说,它看起来像普通的 C。
  • 这是纯 C。感谢编辑。 :)

标签: c


【解决方案1】:

“外部化”一个内存对象/数据结构,例如当通过网络将对象发送到另一个进程或写入文件时,需要将内存对象格式化或转换为可移植表示。指针仅在进程的上下文中才有意义。

通常在发送或写入时将内存对象编码为可移植缓冲区,在接收或读取时将可移植缓冲区解码为内存对象。

几乎所有的 unix/linux/bsd 系统都将外部数据表示、XDR、库例程作为 libc 的一部分。执行“man xdr”以获取更多信息。

xdr 非常适合您使用 C 语言。

【讨论】:

    【解决方案2】:

    您想要实现的是serializationmarshalling,通常在通过网络连接发送数据时完成,这在许多情况下增加了需要跨平台的复杂性。

    这些天来,我认为您应该考虑使用 Google Protocol Buffers 来实现这一点,因为它会为您完成大部分繁重的工作。

    iOS 或 OSX 特定的解决方案也可以是 Core Data

    从根本上说,这些指针在文件中是没有意义的,并且仅在单次调用期间与您的进程相关。

    【讨论】:

      【解决方案3】:

      你可以试试这个代码:

       #include "stdio.h"
      
          struct Address {
              int id;
              int var;
              char *name;
          };
      
          struct Link {
              int link_var;
              struct Address *addr;
          };
      
          int main(int argc, char *argv[])
          {
              FILE *file = fopen("test.dat", "w");
              int i = 0;
      
              //struct Link *link = malloc(sizeof(struct Link) + (sizeof(struct Address)*10) + (10*10));//B2 + 10B1 +100
              struct Link *link = malloc(sizeof(struct Link));
              struct Address addr_container[10];
      
              for(i = 0; i < 10; i++) {
      
                  char temp_name[10];
                  memset(temp_name, '\0', 10);
      
                  temp_name[0] = 'A';
      
                  struct Address addr_proto = {.id = i, .var = 10, .name = temp_name};
      
                  addr_container[i] = addr_proto;
              }
      
              struct Link link_proto = {.link_var = 2, .addr = addr_container};
      
              memcpy(link, &link_proto,sizeof(struct Link));// sizeof(struct Link) + (sizeof(struct Address)*10) + (10*10));
      
              printf("%s\n", link->addr[4].name);
      
              fprintf(file,"link_var : %d\n",(link->link_var));
              for(i = 0; i< 10; ++i)
              {
                   fprintf(file,"Adress id is      :%d\n",(link->addr[i].id));
                   fprintf(file,"Adress var is     :%d\n",(link->addr[i].var));
                   fprintf(file,"Adress name is    :%s\n\n",(link->addr[i].name));
              }
              fclose(file);
              free(link);
      
              return 0;
          }
      

      fwrite()写成二进制,所有数据的内存不连续

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-10-11
        • 2017-04-21
        • 2021-07-25
        • 1970-01-01
        • 2022-01-11
        • 2020-04-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多