如何在联合体中访问结构体并在c++中指向它们

nbysray5  于 2022-12-26  发布在  其他
关注(0)|答案(2)|浏览(131)

我必须基于struct在c中实现一个构造函数:

struct Node {
    char name[MAX_NAME_LEN + 1];
    NodeType type;
    union {
        struct {
            Entry* entries; // list of directory entries
        } dir;
        struct {
            void* contents; // any binary data of the given length
            int length;
        } file;
    };
};

现在我想构建一个file的构造函数,指向内容并以字节为单位保存长度,但不知何故我不知道该怎么做...
下面是我的尝试:我知道我必须为此分配空间,但我如何使这个指针的东西?

Node* new_file(char* name) {
    Node* ptr_file = xmalloc(sizeof(Node));
    ptr_file->name;
    return NULL;
}
9avjhtql

9avjhtql1#

  • 您需要typedef struct { ... } Node才能编译代码。
  • 当使用匿名结构体/联合体时,你只是不给予匿名成员命名。ptr_file->dir.entriesptr_file->file.contents
  • 如果您放弃内部结构体名称并使其匿名,则只需键入ptr_file->entries;

请注意,匿名结构体/联合体在ISO 9899:2011版本的C语言中被添加到了该语言中,因此您需要使用一个相当现代的编译器来使用它们。
顺便说一句,void*可能没有任何意义。我认为您正在尝试做的是:

#include <stdint.h>

typedef struct {
    char name[MAX_NAME_LEN + 1];
    NodeType type;
    union {
        struct {
            Entry* entries; // list of directory entries
        };
        struct {
            uint8_t contents [sizeof(Entry)]; // use to inspect raw data
            int length; // probably not needed
        };
    };
} Node;
nukf8bse

nukf8bse2#

使用Node* new_file(char* name)时,Node尚未定义。代码需要typedef struct Node Node;或类似代码。
这项任务面临的一大挑战是许多潜在的错误可能会悄悄进入:文件名太长,内存分配失败,fopen打开失败,读取失败,文件太长,...
int length;应为size_t length;,因为文件可能比INT_MAX长,但仍适合分配。
new_file(char* name)看起来应该读取一个文件。让我们创建一个辅助函数,因为需要不同程度的健壮性。下面的函数通常“工作”,但属于技术UB(查找到二进制文件的末尾)。根据需要进行调整。
说明性的、未经测试的代码:

// The below does _not_ return a null character appended string,
// just the data in the file. 
void *alloc_file(const char *file_name, size_t *size) {
  *size = 0;
  FILE *binary_stream = fopen(file_name, "rb");
  if (binary_stream == NULL) {
    return NULL;
  }
  
  long offset = fseek(binary_stream, SEEK_END);
  rewind(binary_stream);
  if (offset == -1 || (unsigned long) offset > SIZE_MAX) {
    fclose(binary_stream);  // Trouble or file too long
    return NULL;
  }
  size_t file_size = (size_t) offset;
  void *buf = malloc(file_size) {
    fclose(binary_stream);
    return NULL;
  }
  if (fread(buf, 1, file_size, binary_stream) != file_szie) {
    fclose(binary_stream);
    free(buf);
    return NULL;
  }
  *size = file_size;
  fclose(binary_stream);
  return buf;
}

现在new_file更容易了。

// Better as: Node* new_file(const char* name)
Node* new_file(char* name) {
  if (strlen(name) >= MAX_NAME_LEN) {
    return NULL // name too long
  }      
  // Allocate to the size of the referenced object, not type.
  Node* ptr_file = malloc(sizeof ptr_file[0]);
  if (ptr_file == NULL) {
    return NULL;
  }
  strcpy(ptr_file->name, name);
  ptr_file->type = NodeType_file; // Some constant (OP has not shown yet).
  size_t size = 0;
  ptr_file->file.contents = alloc_file(name, &size);
  if (ptr_file->file.contents == NULL || size > INT_MAX) {
    free(ptr_file->file.contents);
    free(ptr_file);
    return NULL;
  }
  ptr_file->length = (int) size;
  return ptr_file;
}

相关问题