如何在C中定义struct'Atom'?哪个更好?为什么呢?

时间:2015-09-29 09:38:51

标签: c data-structures

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]

所以,当我想为这两种类型的ATOM分配内存时,我也有两种方式。

// 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'的规则,因为'char str [1];''atom2'中

'atom2'真的很好吗?

2 个答案:

答案 0 :(得分:5)

从C99开始,您可以选择使用灵活数组成员 - 即与atom2相同但没有指定数组大小:

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

通过这种方式,您可以在不违反语言规则的情况下将字符串和结构一起分配。

在这种情况下,当您分配内存时,请务必考虑nul字符串终止符:

struct atom2 *p = malloc(sizeof(*p) + len + 1);

(另请注意,您无需转换malloc)的结果。

请注意,您的atom1结构包含的char *char []在语义上不同。指针是占用存储空间的数据成员,可以指向任何位置,而灵活数组成员不占用任何存储空间(除了为其明确分配的存储空间)并始终跟踪对象的其余部分。要使用atom1,您需要分别为struct对象和字符串分配存储空间:

struct atom1 *p = malloc(sizeof(*p));
p->str = malloc(len + 1);

您在问题中建议的分配:

struct atom1 *p = malloc(sizeof(*p) + len + 1);

...至少要求你设置指针p->str,指向正确的位置(类似p->str = ((char *) p) + sizeof(*p)),但我不确定你不会如果您尝试将字符串存储在该位置,则调用未定义的行为。

答案 1 :(得分:0)

atom1没有任何意义,因为你应该为str指向的内容动态分配内存,而不是整个结构。正如代码目前所示,没有一种方法可以使用atom1。

atom2调用未定义的行为。这被称为" struct hack"在旧的C标准,从来没有保证工作。即使您可能在结构的末尾分配了数据,也不允许写出超出固定数组的范围。因为你不知道结构的结束位置:它可能有填充字节。

  

是' 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的数组一样。