Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Empty array declaration - strange compiler behavior

I've found a strange looking piece of code in a project I have to maintain. There's an empty array member of a class which doesn't lead to an compiler error. I've tested some variations of such a code with MSVC 10.0:

template<class T> struct A {
    int i[];
}; // warning C4200: nonstandard extension used : zero-sized array in struct/union

template<class T> struct B { static int i[]; };
template<class T> int B<T>::i[];

struct C {
    int i[];
}; //warning C4200: nonstandard extension used : zero-sized array in struct/union

template<class T> struct D { static int i[]; };
template<class T> int D<T>::i[4];
template<>        int D<int>::i[] = { 1 };


int main()
{
    A<void> a;
    B<void> b;
    C c;
    D<void> d0;
    D<int>  d1;

    a.i[0] = 0;     // warning C4739: reference to variable 'a' exceeds its storage space

    b.i[0] = 0;     // warning C4789: destination of memory copy is too small

    c.i[0] = 0;     // warning C4739: reference to variable 'c' exceeds its storage space

    int i[];        // error C2133: 'i' : unknown size

    d0.i[0] = 0;    // ok
    d0.i[1] = 0;    // ok

    return 0;
}

The error message at int i[] is absolutely sensible to me. The code which is shown with class D is well-formed standard C++. But what's about the classes A, B and C? What kind of types are the member variables int i[] in this classes?

like image 657
0xbadf00d Avatar asked Jul 07 '11 07:07

0xbadf00d


1 Answers

EDIT:

your doubt is explained by the definition of the extension to the language, which allows for zero-sized arrays at the end of structs/unions. I have not tried it, but if you declare another member after the zero-sized array, it should fail.

so, if you allocate a variable on the stack, you have to know its size; the exception to the rule is when allocating an array at the end of a struct/union, where some C-typical trickery is possible.

In c++ this raises a warning because the default copy constructor and assignment operator will probably not work.

PREVIOUS ANSWER:

The compiler warns you about the fact that you are trying to define an array with zero size. This is not allowed in standard C/C++.

Let's see the differences class by class.

In class D:

template<class T> struct D { static int i[]; };

it works because you are just declaring the type of a static member variable. For this to link, you need also defining the actual array, in a definition statement like you do:

 template<>        int D<int>::i[] = { 1 };

here you also specify the size of the array through the initializer.

With class B, you are doing something similar, but the definition is:

 template<class T> int B<T>::i[];

i.e., you don't specify the size and get the warning.

With class A, more of the same, you are defining a member variable of type array without the size.

like image 190
sergio Avatar answered Nov 11 '22 23:11

sergio