Reputation: 593
What's the difference between (1)
char s[5] = {'a', 'b', 'c', 'd', '\0'};
char s2[strlen(s) + 1];
strcpy(s2, s);
And (2)
char s[5] = {'a', 'b', 'c', 'd', '\0'};
char *s2 = malloc(strlen(s) + 1);
strcpy(s2, s);
In what situation should you use each of these? Can you only use the first one when you are certain that the array s
is of a static size?
Upvotes: 3
Views: 163
Reputation: 213720
You actually have three cases to consider: a plain statically allocated array, a variable-length array (VLA, your 1st example) and a dynamically allocated array (your 2nd example).
There are many aspects to consider, there's no black or white answer.
The actual need of the application: If the amount of items is known at compile-time, there is usually no need to use dynamic memory allocation (except for large amounts of data, as mentioned later in this answer).
Note that if the program design is at all sound, there always exists a worst-case scenario of an upper limit of items allocated, since no program can handle unlimited amounts of data. Depending on how many items that are needed for the worst-case scenario, you'll have to make a decision whether or not to use dynamic allocation. As a rule of thumb, use dynamic allocation when the number of items is vast.
It also doesn't make any sense to use dynamic memory allocation on single-process systems (such as bare metal embedded systems), since there is none to share the RAM with. Such systems can just allocate the whole RAM statically, as it has free access to 100% of the system resources.
Performance: Statically allocated arrays are the fastest. VLAs are likely not much slower, but may introduce a bit of overhead code. Dynamic allocation on the heap is the slowest, as it involves lookups, several function calls, fragmentation handling etc.
Process memory preservation: On all the mainstream operative systems, processes have a limited amount of stack and .data/.bss memory. The heap however, is far less limited, likely limited to the amount of RAM present in the computer where the program is running. Therefore, when allocating large amounts of memory, one should always use dynamic memory allocation.
Safety: Dynamic memory allocation is notoriously dangerous, because it leads to memory leaks and heap fragmentation. In embedded systems programming, dynamic memory allocation is usually banned entirely for these reasons, and it is banned in every safety-related programming standard as well.
Compatibility/portability: VLAs were introduced in the C99 standard and will not compile on ancient compilers. In C11, VLAs are no longer mandatory to implement, although in practice I very much doubt any C11 compiler will refuse to implement them. C++ does not support VLAs.
The main benefit of VLA, in my opinion, is not to allocate arrays, but that it enables you better type safety for pointer types. For example VLAs enable functions like this void func (int x, int y, int array[x][y]){}
, where array
is actually a pointer, not an array.
A side note: both of your examples are poorly written performance-wise. They should both be using sizeof(s)
instead of strlen.
Upvotes: 1
Reputation: 134326
In case 1,
char s2[strlen(s) + 1];
s2
is an array. In case 2,
char *s2 = malloc(strlen(s) + 1);
s2
is a pointer.
FWIW, the first approach won't work if the compiler does not support VLA.
As per the latest standard, C11
, VLA is an optional feature which compiler(s) is (are) not bound to support. The second approach, is an integral part of C standard (library) and available without any additional requirement of the compiler support.
Upvotes: 7