在一个C++开源项目中,我看到了这一点.
struct SomeClass {
...
size_t data_length;
char data[1];
...
}
Run Code Online (Sandbox Code Playgroud)
这样做有什么好处而不是使用指针?
struct SomeClass {
...
size_t data_length;
char* data;
...
}
Run Code Online (Sandbox Code Playgroud)
我唯一能想到的是使用size 1数组版本,用户不会看到NULL.还有别的事吗?
Joh*_*itb 36
有了这个,您不必在其他地方分配内存并使指针指向它.
诀窍是分配更多的内存sizeof (SomeClass),并SomeClass*指出它.然后,您的SomeClass对象将使用初始内存,并且可以使用剩余的内存data.也就是说,你可以说p->data[0]也是p->data[1]等,直到你打你分配内存的结束.
可以指出这种使用会导致未定义的行为,因为您声明您的数组只有一个元素,但是访问它就像它包含更多元素一样.但是真正的编译器确实允许这个具有预期意义,因为C++没有替代语法来形成这些方法(C99有,它在那里被称为"灵活的数组成员").
Lyk*_*yke 19
这通常是避免多个内存分配和解除分配的快速(和脏)方式,尽管它比C++更时尚.
也就是说,而不是这个:
struct SomeClass *foo = malloc(sizeof *foo);
foo->data = malloc(data_len);
memcpy(foo->data,data,data_len);
....
free(foo->data);
free(foo);
Run Code Online (Sandbox Code Playgroud)
你做这样的事情:
struct SomeClass *foo = malloc(sizeof *foo + data_len);
memcpy(foo->data,data,data_len);
...
free(foo);
Run Code Online (Sandbox Code Playgroud)
除了保存(de)分配调用之外,这还可以节省一些内存,因为没有指针的空间,你甚至可以使用原本可能是struct padding的空间.
Ed *_* S. 11
它们在您的示例中在语义上是不同的.
char data[1]是一个有效的char数组,在堆栈上分配了一个未初始化的元素.你可以写data[0] = 'w',你的程序是正确的.
char* data; 简单地声明一个无效的指针,直到初始化为指向有效地址.
Ben*_*tto 10
通常您将此视为结构的最终成员.然后,无论malloc结构是谁,都将在内存中连续分配所有数据字节作为一个块来"跟随"结构.
因此,如果您需要16个字节的数据,您将分配一个这样的实例:
SomeClass * pObj = malloc(sizeof(SomeClass) + (16 - 1));
Run Code Online (Sandbox Code Playgroud)
然后,您可以像访问数组一样访问数据:
pObj->data[12] = 0xAB;
Run Code Online (Sandbox Code Playgroud)
当然,你也可以通过一次通话释放所有的东西.
data按惯例,该成员是单项数组,因为较旧的C编译器(显然是当前的C++标准)不允许零大小的数组.这里有很好的进一步讨论:http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html