簡體   English   中英

如何訪問聯合中的結構並在 c 中指向它們

[英]How to access structs in Unions and point to them in c

我必須基於這個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;
}
  • 您需要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;

對於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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM