Reputation: 63
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
Reputation: 36
Move your test into a new function called from the main(), then you should see the stack-smashing.
Upvotes: 0
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
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
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
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