I'm sitting at my desktop, attempting to implement a C++
code snippet I found freely offered online into my program, and I start modifying it in order to make it fit the requirements of my computer. The code snippet in question uses enum
in order to define a certain set of constants to perform calculations with. My program, on the other hand, needs to be able to deal with varying values that should be calculated at runtime
. This generally isn't much of a problem, as all you usually need to do is declare the global constant
as a global variable
, and then make sure to initialize
Except that there are one or two places in the C and C++ programming languages where a constant works, but variables do not.
static UserDefinedClass* g_Array[FOO][BAR];
and have been properly declared, this works perfectly. If, on the other hand, you've changed them into variables
instead, you have a problem on your hands, and justifiably so. If they are variables, how is the compiler
supposed to know how much memory
to the array
The solution is to dynamically allocate the array AFTER you have filled the sizing variables with useful data.
Before we make ourselves a nice multidimensional array, let's stick with a monodimensional one first, just to make sure we understand the theory fully.
What we're going to do is tell the compiler to allocate us a single block of memory. That memory will store a pointer, which points to the data type we want to store into the array.
Now then, later in the program, when we need to fill the array out, we now can force feed more memory space into our greedy little paws. We can do this the oldskool way, with malloc, or the newskool way, with new. Let's use both, just for giggles. In the following examples, we'll be making a simple integer array with n elements. Just for the heck of it, n will be set to 1000.
Oldskool ANSI C way
Newskool C++ method
a = (int*) malloc(n*sizeof(int));
a = new int[n];
Both do the exact same thing. Each changes the pointer stored in the variable 'a' to point to a new memory address, and that memory address has now been dynamically cleared to allow for n
members of type int. Pretty cool, huh? although, personally, just between you and me, I prefer the newskool way-- don't tell the hip crowd, okay?
So now we can get ourselves a nice dynamic 1D array at runtime with a variable size. But that doesn't help me now does it? What about my needs? I need a two-dimensional array at runtime. So how am I going to manage THAT?
What I really need here is an array of pointers. Fortunately enough, we can make those easily enough. Heck, we can make pointers to pointers to pointers to pointers to pointers all we want, and it's little more difficult than making a simple pointer. You just need to learn to count asterisks. In this case, we're going to need two.
Will do the job nicely. But now how do we dynamically allocate all the memory we need? Well, first we allocate the first dimension, and then we use a for loop to allocate all the sub layers. Quite simple! Just watch. m
will be the size of our second dimension, which just for the sake of picking a number at random, will be set to 20.
Oldskool ANSI C way
Newskool C++ method
a = (int**) malloc(n*sizeof(int*));
for(i=0; i<n; i++)
a[i] = (int*) malloc(m*sizeof(int));}
a = new int*[n];
a[i] = new int[m]}
Something to note is that even though we're declaring these arrays dynamically, we can still use standard array notation in order to get at member elements. This holds true for both C and C++. This is because the array notation is quite literally just shorthand for pointer addition. (a[i]) is exactly the same thing as (a+i) as long as a is a pointer type variable. It's just that it's easier for humans to think in terms of arrays rather than pointers. But to the computer, it's all the same.
The same method for expanding a single dimension array into a two dimensional array can be used to extend into n-dimensional arrays quite simply. All you need to do is stick another for loop after each dimension you allocate, and don't forget to count the asterisks you need for each level!
It may be worthwhile to note that there is a way to allocate pseudo-multidimensional arrays without ever touching a loop, but it can cause a few headaches later on. It works like this: where i, j, k are the variables for the dimension sizes...
array = (type) malloc(i*j*k * sizeof(type));
This will gain you an array able to fit all your elements, but no longer can you use the nice array[x][y][z] indexing method. Now you must use the rather unwieldy
array[x + k * (y + j * z)]
Which is not nice at all. You have to keep track of the size of each dimension in order to access any element! Personally, I'd rather just stick to the for loops
, thanks kindly. If circumstances do not allow you that luxury, I weep for your soul. Try to keep track of things as best you can and remember to comment extensively.