使用可变长度数组成员分配struct

Cli*_*ton 8 c++ new-operator dynamic-memory-allocation c++11

我知道我可以new char[n]创建一个n字符数组.即使n不是编译时常量,这也可以工作.

但是让我说我​​想要一个大小变量后跟n个字符:

我的第一次尝试是:

struct Test
{
  std::size_t size;
  char a[];
};
Run Code Online (Sandbox Code Playgroud)

然而,似乎new Test[n]没有做我期望的,而是分配n sizes.

我还发现sizeof(std::string)在ideone处是4,所以它似乎可以在一个块中分配size和char数组.

有没有办法实现我所描述的(大概是std::string已经做过的)?

Ada*_*ras 11

虽然你可以这样做(并且它经常在C中用作各种解决方法),但不建议这样做.但是,如果这真的是你想做的......这是大多数编译器(包括那些不能很好地使用C99增强功能的编译器)的方法.

#define TEST_SIZE(x) (sizeof(Test) + (sizeof(char) * ((x) - 1)))

typedef struct tagTest
{
    size_t size;
    char a[1];
} Test;

int elements = 10; // or however many elements you want
Test *myTest = (Test *)malloc(TEST_SIZE(elements));
Run Code Online (Sandbox Code Playgroud)

C99之前的C规范不允许在结构内使用零长度数组.要解决此问题,将创建一个包含单个元素的数组,并将一个小于请求的元素数的数组添加到实际结构的大小(大小和第一个元素)以创建预期大小.

  • 除非你使用编译器指令手动设置结构的打包,如果你有一个`short`作为第一个成员并将数组定义为`long`,编译器将在字节0(通过字节1)启动`short` ,跳过字节2到7,然后在字节8处启动`long`(保持正确对齐).然后,在此之后分配/访问的每个"long"将是8字节对齐. (2认同)

Mig*_*uel 9

你可以使用placement new:

#include <new>

struct Test {
    size_t size;
    char a[1];

    static Test* create(size_t size)
    {
        char* buf = new char[sizeof(Test) + size - 1];
        return ::new (buf) Test(size); 
    }

    Test(size_t s) : size(s)
    {
    }

    void destroy()
    {
        delete[] (char*)this;
    }
};

int main(int argc, char* argv[]) {
    Test* t = Test::create(23);
    // do whatever you want with t
    t->destroy();
}
Run Code Online (Sandbox Code Playgroud)


Yan*_*min 7

您还可以使用"长度1阵列"技巧.这是在C:

struct Test {
    size_t size;
    char a[1];
}

int want_len = 2039;
struct Test *test = malloc(sizeof(struct Test) + (want_len - 1));
test->size = want_len;
Run Code Online (Sandbox Code Playgroud)

GCC还支持"0长度"数组,用于此目的:http: //gcc.gnu.org/onlinedocs/gcc/Zero-Length.html

  • 这被称为["struct hack"](http://c-faq.com/struct/structhack.html). (2认同)