0

Seems like a weird question but when I program in C++ or C for example I have to hard code the size of the array.

Is it not possible for the user via terminal to enter the size? So far I can't seem to see if it's possible and wondering why this is forbidden.

EDIT:

So far what I understand is arrays are static and we can use link lists as they're more dynamic. Why can't arrays be dynamic?

Community
  • 1
  • 1
lecardo
  • 1,208
  • 4
  • 15
  • 37
  • 3
    The title speaks of changing the size of an array, which I take as "turn an existing array of size N into an array of size M". But the body seems to focus on creating an array with a size that is decided at run time, but fixed after array creation. Which one is it? –  Feb 24 '14 at 23:36
  • 2
    C or C++? Pick one please. – Lightness Races in Orbit Feb 24 '14 at 23:40
  • 1
    The answer is not the same in C and C++. C does allow for VLA's (variable length arrays), you're just using an outdated compiler. – Ed S. Feb 24 '14 at 23:58
  • That said, VLA's sized from user input are a bad idea anyway. – Ed S. Feb 25 '14 at 00:39
  • Since you tagged as C++, save yourself some pain and use `std::vector`. – Thomas Matthews Feb 25 '14 at 00:51
  • possible duplicate of [C++ Static array vs. Dynamic array?](http://stackoverflow.com/questions/2672085/c-static-array-vs-dynamic-array) – csl Feb 25 '14 at 08:04

5 Answers5

4

std::vector is a dynamic array. Use that.

Variable-length arrays do actually exist in C, and as a GCC language extension for C++, and in the forthcoming C++14 by the look of it.


In this answer, I have assumed you mean arrays that can have runtime bounds, even if those bounds cannot later be altered. This matches the content of your question, but not its title. Fortunately, std::vector provides for both.

I have also assumed C++, because who are we kidding?

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
3

C

In C99 and newer standards, you can use VLAs:

int len = ask_length_from_user();
int array[len];
for (int i = 0; i < len ; ++i) array[i] = i;

Note that with VLAs, you should be careful about the size, because VLA will be stored in stack, which is often quite limited (only megabytes, instead of gigabytes of max heap).

Perhaps better is to use heap:

int len = ask_length_from_user();
int *array = malloc (sizeof(int) * len);
if (!array) exit(1); // malloc failed
for (int i = 0; i < len ; ++i) array[i] = i;

Note how you can access allocated memory with same syntax as you would access an array. Also, you can resize memory allocated with malloc:

int tmplen = ask_length_from_user();
int *tmparr = realloc(array, sizeof(int) * tmplen);
if (tmparr) {
    array = tmparr;
    // note: following loop doesn't do anything if len >= newlen
    while(len < tmplen) array[len++] = len;
}
// else realloc failed, keep original array and len

Finally, with malloced memory, remember!

free(array);

C++

You should use for example std::vector:

int len = ask_length_from_user();
std::vector<int> array;
for (int i = 0; i < len ; ++i) array.push_back(i);

// alternatively, you can resize the array and use indexes like in C snippets:
array.resize(len);
for (int i = 0; i < len ; ++i) array[i] = i;

And code for resize, just with push_back:

int tmplen = ask_length_from_user();
if (tmplen < len) { 
    len = tmplen;
    array.resize(tmplen);
} else {
    while (len < tmplen) array.push_back(len++);
}

As you can see, C and C++ codes are totally different. They are different languages, and it seldom makes sense to ask same thing about both. C code (except VLAs in current standard C++) would work in C++, but doing that is not a good idea, it's not good C++, and at least you should avoid malloc and use new (though it does not support resizing nicely).

hyde
  • 60,639
  • 21
  • 115
  • 176
3

It was a design decision of C that the built-in arrays be a simple and fast structure that reflects operations that can be cheaply achieved by the processor. In languages with variable sized arrays the act of resizing an array can be very costly, as underneath code will be called to reallocate a new block of memory a different size, and the copy the existing contents.

In C, you supervise these resizing operations yourself using the heap and malloc / realloc, because that's the sort of language C is. C++ has arrays that do this for you like std::vector, or even in C you can use library functions to manage dynamic arrays. It's just the simple C array is designed to be simple and fast.

sj0h
  • 902
  • 4
  • 4
2

When you allocate a block of memory you do just that - a block of memory the size you asked for is allocated and you are given a pointer to it.

If you try and go beyond the end of that block you are reading/writing to memory that does not belong to the array.

In order to expand the array you need more memory - but your block is not big enough for that. You need to allocate a new block and change your pointer to that new block, you cannot do it by resizing the existing one as the space after your block could already be used by something else!

This is why it's impossible to resize an existing array.

Tim B
  • 40,716
  • 16
  • 83
  • 128
  • That answers the question in the title, but not necessarily the question in the body (I'm not 100% sure). –  Feb 24 '14 at 23:38
  • @delnan He asked why resizing arrays is forbidden in the question body too, the answer is because it's not possible due to the way memory is allocated underneath them... – Tim B Feb 24 '14 at 23:39
  • Where is that asked in the question body? –  Feb 24 '14 at 23:41
  • @delnan you are right, the line in the body is ambiguous. It could mean resizing as in the question title - but it could also mean allocated at run time. – Tim B Feb 24 '14 at 23:43
0

Because static (automatic) variables are allocated on stack, and the address of a function's stackframe is fixed during the function's lifetime. Once you declare an array at some position then you cannot make it larger without overlapping the memory region after it. That's the answer for the question in the title

However in the body you're actually talking about the ability to specify size at runtime as others said. This one is a different question, but C99 does allow variable-length arrays whose sizes are only known at runtime. In C++ or older C standards you can use _alloca or alloca depending on the platform to achieve the same goal. But in any cases those arrays are still allocated on stack (hence will be limited in size) and their sizes are still fixed, you cannot resize it after declaring for the same reason

To be able to enlarge the array or declare a big array you must allocate dynamic memory on heap and use the returned pointer as array because in C and C++ arrays also decay to pointers in most cases. Dynamically allocated memory can be resized by resizing the allocation if there are enough free blocks after the currently allocated ones, or by allocating a new memory region, copy the data to the new location and then free the old memory blocks

Why can't arrays be dynamic?

Because the philosophy of C and C++ is that "you don't pay for what you don't use" so if you want to allocate memory dynamically you must explicitly do that. Static allocation is much faster and doesn't require one to free after use. That said the standard containers in C++ abstract the dynamic memory usage and should be used instead if you're in C++. Among those, vector, string, deque in the std namespace are the most similar to a dynamic array. That said, linked lists as you mentioned are not dynamic arrays in anyway. They must be accessed in sequential order. Random access is not possible

phuclv
  • 37,963
  • 15
  • 156
  • 475