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