ATOM是指一个指针,它指向独占的常量字符串。
“C”中的字符串应以“\0”结尾。
我将展示两种在“C”中定义“ATOM TABLE”结构的方法:

struct atom1 {
    struct atom1 *link;
    int len;
    char *str;
} *bucket[2048]


struct atom2 {
    struct atom2 *link;
    int len;
    char str[1];
} *bucket[2048]

所以,当我想为这两种类型的原子分配内存时,我也有两种方法。
// memory + 1 for '\0'
struct atom1 *p = malloc(sizeof(*p) + len + 1);


// memory for '\0' is already in the define of struct atom
struct atom2 *p = malloc(sizeof(*p) + len);

所以我们可以看到,当我们想分配内存时,“atom2”看起来更好。但另一方面,如果我们想访问字符串的内存,我们将打破“C”的规则,因为“atom2”中有“char str[1];”。
“atom2”真的很好吗?

最佳答案

atom1没有任何意义,因为您应该为str所指向的对象动态分配内存,而不是为整个结构分配内存。按照目前的代码,您将无法使用atom1。
atom2调用未定义的行为在旧的C标准中,这被称为“struct hack”,而且从来没有保证它能工作。不允许写入固定数组的越界,即使您可能已在结构的末尾分配了数据。因为您不知道结构的结尾:它可能有填充字节。
“atom2”真的很好吗?
两种方法都不好,两种都不要用。在现代C中,可以通过使用灵活的数组成员以安全的方式实现这一点:

typedef struct atom3
{
  struct atom3* link;
  size_t        lenght;
  char          str[];
} atom3_t;

然后将内存分配为:
atom3_t* p = malloc(sizeof(*p) + length + 1);

之后,您就可以安全地使用str了,就好像它是任何大小length + 1的数组一样。

09-16 00:10