static arrays defined with unspecified size, empty brackets?

让人想犯罪 __ 提交于 2019-11-29 06:40:52

C99 supports something called a 'flexible' array member that is allowed to be the last member of a struct. When you dynamically allocate such a struct you can increase the amount requested from malloc() to provide for memory for the array.

Some compilers add this as an extension to C90 and/or C++.

So you can have code like the following:

struct foo_t {
    int x;
    char buf[];
};


void use_foo(size_t bufSize)
{
    struct foo_t* p = malloc( sizeof( struct foo_t) + bufSize);

    int i;

    for (i = 0; i < bufSize; ++i) {
        p->buf[i] = i;
    }
}

You can't define a struct with a flexible array member directly (as a local or a global/static variable) as the compiler won't know how much memory to allocate for it.

I'm honestly not sure how you'd easily use such a thing with C++'s new operator - I think you'd have to allocate the memory for the object using malloc() and use placement new. Maybe some class/struct specific overload of operator new could be used...

C++ language allows omitting array size only in non-defining declarations

extern int a[]; // non-defining declaration - OK in C++

int a[]; // definition - ERROR in C++

int a[5]; // definition - OK, size specified explicitly
int a[] = { 1, 2, 3 }; // definition - OK, size specified implicitly

Non-static class member decarations are always required to specify the array size

struct S {
  int a[]; // ERROR in C++
};

while static class member decarations can omit the size

struct S {
  static int a[]; // OK in C++
};

(the definition of the same member will, of course, have to specify the size).

Any deviations from this behavior can only be explaind by extended non-standard behavior of your compiler. Maybe you should specify some additional compiler settings to make it behave in more pedantic fashion.

class Foo {
    int a[]; // OK in C, invalid in C++. Does not work with inheritance.
}; // Idea is that structure is "extended" indefinitely by an array.
   // May work on your compiler as an extra feature.

int a[];     // error in C and C++: storage size of 'a' isn't known

void bar() {
    int a[]; // error in C and C++: storage size of 'a' isn't known
}

extern int a[]; // OK: storage size may be declared later.

int a[5]; // declaration of size before use.

An array type with unspecified size is incomplete. 8.3.4/1:

If the constant expression is omitted, the type of the identifier of D is “derived-declarator-type-list array of unknown bound of T”, an incomplete object type.

It must be completed in order to participate in a definition, ie the definition of a must contain a size specification or initialization with an array of specified size.

We've used this to denote a variable length record of some sort. Something like a header file that has information on how many structures to follow, followed by the data itself. It's a variable length array and I've found it is not supported well between compilers. Some want array[]; and some want array[0]; (old style).

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!