1

I am receiving "Segmentation fault" when I try to populate my array. So I was think of declaring the arrays size in the class to declare the array's size so it can allocate the space, but I receive.

error: invalid use of non-static data member ‘Array::Size’ error: from this location

//Current
class Array{
    public:
    int Size;
    int Range;
    int Array[];
};


//Problematic 
class Array{
    public:
    int Size;
    int Range;
    int Array[Size];
};

or there any other method of preventing an Segmentation fault?

johnkavanagh
  • 4,614
  • 2
  • 25
  • 37
Mitt.R
  • 11
  • 1
  • 2

3 Answers3

3

You're attempting to use a C idiom, where the last member of a structure is a very short array (one or, if permitted by the compiler as a nonstandard extension, zero elements) and extra memory is allocated for the structure so elements beyond the end of the declared array can be accessed. This was originally a nonstandard trick, known as the struct hack, or in some compilers as zero-length arrays. It was standardized in C99 as flexible arrays.

When you used this idiom, you needed to allocate additional memory for the array, e.g. sizeof (struct Array) + sizeof (int) * number_of_elements. Otherwise you wouldn't have memory allocated for more elements than you actually declared (usually one or zero), and you'd get undefined behaviour when you tried to access elements beyond that.

However, you're writing C++, not C99. Even if your compiler allows you to do this, relying on it would be very bad practice, and a lot more awkward C++ than in C.

Either store a pointer in the class and allocate the appropriate amount of memory in the constructor, and deallocate it in the destructor, or use a C++ class that will manage the memory for you, e.g. std::vector.

Here's an example of using std::vector:

#include <vector>

class Array{
    public:
        int size;
        int range;
        std::vector<int> array;

        Array(int size, int range) :
            size( size ),
            range( range ),
            array( size, 0 )
        {
        }
};
Community
  • 1
  • 1
svk
  • 5,854
  • 17
  • 22
  • @Constantin No, `int Array[];` isn't a valid way to declare an `int*`. Your code doesn't seem to compile for me. See [here](http://ideone.com/YmvpYc). – svk Nov 29 '13 at 11:43
  • It's called "flexible array" in C99. "Zero-length" would be something like `int a[0]`, which was never standard and is available only as an extension on certain compilers. – Kerrek SB Nov 29 '13 at 12:25
  • @KerrekSB Tried to clarify, better? Pre-C99 it's my understanding that the trick was nonstandard but still in widespread use, though maybe as `int a[1]` rather than `int a[0]`. – svk Nov 29 '13 at 12:47
  • @svk: So, `int a[1]` would actually be standard, though allocating and accessing more memory was not (in C89) -- but you'd always need to deal with the annoying off-by-one. I believe `int a[0]` (strictly as a struct member!) was accepted by some compilers to overcome the off-by-one issue, and finally got standardized as `int a[]` in C99... – Kerrek SB Nov 29 '13 at 13:55
  • @KerrekSB Well, sure, `int a[1]` was always standard as a declaration of an array of a single element, but that seems like a technicality if one wasn't ever actually allowed to access `a[1]` after allocating some extra memory. – svk Nov 29 '13 at 14:01
1

Both these definitions

//Current
class Array{
public:
int Size;
int Range;
int Array[];
};
//Problematic 
class Array{
public:
int Size;
int Range;
int Array[Size];
};

are invalid. The first one is invalid because class definition may not containg incomplete non-static data members. You may not write int Array[]; The second one is invalid because 1) data member Size has undefined value and 2) the size of an array shall be a constant expression. Instead of declaring array you could use a pointer and dynamically allocate an array of the required size.

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

You can use pointer.

class Array{
public:
int Size;
int Range;
int* Array;
};

In the constructor, you can allocate memory for it. Or maybe you can do it in a member function.

Array::Array(/*parameters*/){
/* code */
Array = new int [Size] //After Size is initialized or assigned.
}

In the destructor, you should use delete[] Array to deallocate the memory.

Lucifer
  • 21
  • 2