0

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

Westbrook
  • 63
  • 6
  • 3
    Zero-sized arrays are not part of standard C++. (Actually the proper term is flexible array member.) –  Oct 28 '14 at 17:15
  • 1
    Related to: [What is the use of 0-length array (or std::array)?](http://stackoverflow.com/q/26209190/1708801) ... `char array[]` is a flexible array member which is a compiler extension. – Shafik Yaghmour Oct 28 '14 at 17:17
  • This isn't C++. In C there are "flexible arrays", but C is a different language. – Kerrek SB Oct 28 '14 at 17:18
  • Thanks I will look into flexible arrays. Btw, is obj2's array member stored on the stack in the example in my post? – Westbrook Oct 28 '14 at 17:21

5 Answers5

4

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.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
3

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.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

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.

Patrik Valkovič
  • 706
  • 7
  • 26
1

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.

0

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

tugak
  • 36
  • 2