When I try to run this, it gives me an error saying that the value in variable a
isn't constant. That doesn't make sense to me because I explicitly made the variable a
constant. Does the size of an array have to more constant than that? Meaning, only #define a 5
, or initializing it as int arr[5]
or using malloc
? What is wrong with what I did?
int main{
const int a = 5;
int i;
int arr [a];
for (i = 0; i < 5; i++) {
arr[i] = i * 2;
}
printf("%d", arr[1]);
return 0;
}
Array size. The size of an array is the product of the lengths of all its dimensions. It represents the total number of elements currently contained in the array. For example, the following example declares a 2-dimensional array with four elements in each dimension.
In C the type of character constant is integer (int). So in C the sizeof('a') is 4 for 32bit architecture, and CHAR_BIT is 8. But the sizeof(char) is one byte for both C and C++.
Declaring ArraysArray variables are declared identically to variables of their data type, except that the variable name is followed by one pair of square [ ] brackets for each dimension of the array. Uninitialized arrays must have the dimensions of their rows, columns, etc. listed within the square brackets.
Arrays are Not Constants It does NOT define a constant array. It defines a constant reference to an array. Because of this, we can still change the elements of a constant array.
To get the size of an array, you can use the sizeof () operator: Why did the result show 20 instead of 5, when the array contains 5 elements? It is because the sizeof () operator returns the size of a type in bytes.
It has become a common practice to declare arrays using const: An array declared with const cannot be reassigned: The keyword const is a little misleading. It does NOT define a constant array. It defines a constant reference to an array. Because of this, we can still change the elements of a constant array.
In C, the array sizer must be a constant expression (C99 allows VLA under certain conditions. Note that today's implementations of VLA are broken, even with gcc 4.x).
(If you don't use link-time optimization to let them inline the value.) It's simply a limitation of the language. The sizes of statically-bounded arrays need to be constant expressions, and unfortunately in C that's only something like a literal constant or a sizeof expression or such like, but not a const -typed variable.
Maybe use an enum to define the value of a
.
enum { a = 5 };
int arr [a];
Perhaps this is not the intention of an enum but the members of enums are the closest thing to a constant in C. Unlike the common practice of defining everything using #define
, the visibility of a
is limited by scope and here it is the same as arr
.
In C, const
should be read as read-only. It doesn't define a compile time.
const int a = 5;
Here a
, is not a constant expression as required by the C standard:
6.7.9 Initialization
4 All the expressions in an initializer for an object that has static or thread storage duration shall be constant expressions or string literals.
So the error indicates you are using a C89/C90 compiler. You can read the input from user for a
and declare a variable length array, which is a C99-feature, which has automatic storage duration.
Using #define
is another way. But it's simply a textual replacement and defines an array with automatic storage duration. It's same as defining int arr[5];
yourself.
if you want to allocate memory on dynamic storage (commonly known as "heap"), you have to use malloc()
family functions, which will have lifetime thoughout the program execution until you call free()
on it.
(Note that this behaviour of const
is only in C. C++ differs in this and will work as you expected).
If I compile the code in C89, it fails with:
#include <stdio.h>
int main(){
const int a = 5;
int i;
int arr [a];
for (i = 0; i < 5; i++) {
arr[i] = i * 2;
}
printf("%d", arr[1]);
return 0;
}
$ gcc -Wall -Wextra -std=c89 -pedantic-errors test.c
test.c: In function âmainâ:
test.c:7:4: error: ISO C90 forbids variable length array âarrâ [-Wvla]
int arr [a];
^
because C89 doesn't support VLAs (Although gcc supports it as an extension even in C89/C90). So if you are using a compiler that doesn't support C99 then you can't use VLAs. For example, visual studio doesn't fully support all C99 and C11 features. Although, Visual studio 2015 support most C99 features, VLAs are not one of them.
But the same code compiles in C99 and C11 without any problem:
$ gcc -Wall -Wextra -std=c99 -pedantic-errors t.c
$ gcc -Wall -Wextra -std=c11 -pedantic-errors t.c
It's because variable length arrays (VLAs) were added in C99. Note that VLAs have been made optional in C11 standard. So an implementation may not support VLAs in C11.
You need to test against __STDC_NO_VLA__
to check if VLAs are not supported by your implementation.
From 6.10.8.3 Conditional feature macros
__STDC_NO_VLA__
The integer constant 1, intended to indicate that the implementation does not support variable length arrays or variably modified types.
I personally do not use VLAs as the allocation failure can't be portably found if the array size is reasonably large. E.g.
size_t size = 8*1024;
int arr[size];
In the above fragment, if arr
allocation failed, you won't know it until runtime. What's a "small enough" size for which the memory allocation is platform dependent. So on one machine, 1MB allocation may succeed and another it may fail and worse part is that there's no way to catch this failure.
Thus the use of VLAs is limited and can only be used with small arrays that you know will always succeed on a given platform. But in that I would simply hard-code the array size and take care of the boundary conditions.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With