Westbrook
Westbrook

Reputation: 63

Array data members declared with no size

I'm trying to understand how arrays work in C++. Some good threads on SO, but one question I have that I can't find the answer to is:

Why is it possible to declare array data members with no size? I thought in C++ an array size had to be a compile-time constant?

Example:

#include<iostream>

class Object{

public:
      Object(std::size_t n){  

        for(std::size_t i = 0; i<n; ++i) { array[i] ='X'; }

        //prints 0 because 'sizeof' is compile-time operator
        std::cout << "compile-time size: " << sizeof(array) << std::endl;
        std::cout << "run-time size " << n << std::endl;
      }

private:
      char array[];
};  

int main( int argc, char** argv )
{
  Object obj(10);      //10 chars

  std::size_t n;
  std::cin >> n;
  Object obj2(n);      //n chars in automatic storage i.e. on the stack??
}

Input: 
  n = 1000
Output: 
  compile-time size: 0
  run-time size 10
  compile-time size: 0
  run-time size 1000

Does this mean that obj2's array data member is stored in automatic storage, but the size is determined dynamically at runtime ?

Thanks

Upvotes: 0

Views: 1206

Answers (5)

tugak
tugak

Reputation: 36

Move your test into a new function called from the main(), then you should see the stack-smashing.

Upvotes: 0

Vlad from Moscow
Vlad from Moscow

Reputation: 310930

According to the C++ Standard (9.2 Class members)

9 Non-static (9.4) data members shall not have incomplete types. In particular, a class C shall not contain a non-static member of class C, but it can contain a pointer or reference to an object of class C.

So it is either a compiler feature or its bug.

An array as a non-static data member of a class is stored where the corresponding object of that class was allocated.

As for C then C allows to define flexible array members of structures.

From the C Standard (6.7.2.1 Structure and union specifiers)

18 As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a flexible array member

But in this case a structure shall have more than one named member.

Upvotes: 3

Mike Seymour
Mike Seymour

Reputation: 254431

Why is it possible to declare array data members with no size?

In standard C++, it isn't. In C, you can put one at the end of a struct, to allow a variable-size array - but you must make sure you allocate enough storage for whatever size you want to use. Some C++ compilers may allow this as a non-standard extension.

Does this mean that obj2's array data member is stored in automatic storage, but the size is determined dynamically at runtime ?

No, it means there isn't any storage for the array, and you're writing over other parts of the stack. That's not a good idea.

If you want a dynamic array, use std::vector.

Upvotes: 4

Patrik Valkovič
Patrik Valkovič

Reputation: 724

No way. char array[] is same as pointer to char. That means that you can do this.

char* pointer;
char array[];
array=pointer;

Pointers have value, which was in memory when was pointer created. Simply points somewhere into memory.
Arrays work the same way as pointers. If int have 4bytes, array[5] points to int 5*4=20 after bytes that pointer.

int array[];
array[5];
*(array+5);

C++ doesnt throw exception after crossing the array. Usually shoud program crash because pointers by default point to place somewhere in memory out of the program.

Upvotes: 1

user3920237
user3920237

Reputation:

C99 allows a feature called flexible array members. This is described in §6.7.2.1/18 of the C11 standard:

As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a flexible array member. In most situations, the flexible array member is ignored.

They are not a part of C++, but some compilers allow their use as an extension. For example, GCC explicitly notes this on their C extensions page:

Some features that are in ISO C99 but not C90 or C++ are also, as extensions, accepted by GCC in C90 mode and in C++.

For compatibility, Clang generally implements GNU extensions. Note that using sizeof on said member either appears to be a GCC bug or extension:

Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero.

Additionally, a flexible array member being the sole data member in class is a GNU extension.

Upvotes: 1

Related Questions