Why is the size of array as a constant variable not allowed in C but allowed in C++?
In C const
doesn't mean "constant" (i.e., evaluable at compile time). It merely means read-only.
For example, within a function, this:
const int r = rand();
const time_t now = time(NULL);
is perfectly valid.
The name of an object defined as const int
is not a constant expression. That means that (in C prior to C99, and in all versions of C++) it can't be used to define the length of an array.
Although C99 (and, optionally, C11) support variable-length arrays (VLAs), they can't be initialized. In principle, the compiler doesn't know the size of a VLA when it's defined, so it can't check whether an initializer is valid. In your particular case, the compiler quite probably is able to figure it out, but the language rules are designed to cover the more general case.
C++ is nearly the same, but C++ has a special rule that C lacks: if an object is defined as const
, and its initialization is a constant expression, then the name of the object it itself a constant expression (at least for integral types).
There's no really good reason that C hasn't adopted this feature. In C, if you want a name constant of an integer type, the usual approach is to use a macro:
#define LEN 5
...
int arr[LEN] = {1, 2, 3, 4, 5};
Note that if you change the value of LEN
, you'll have to re-write the initializer.
Another approach is to use an anonymous enum
:
enum { LEN = 5 };
...
int arr[LEN] = {1, 2, 3, 4, 5};
The name of an enumeration constant is actually a constant expression. In C, for historical reasons, it's always of type int
; in C++ it's of the enumeration type. Unfortunately, this trick only works for constants of type int
, so it's restricted to values in the range from INT_MIN
to INT_MAX
.
C: Constant length doesn't allow me to declare array
In C opposite to C++ using a constant object in a declaration of an array like this.
const int SIZE = 5;
int grades[SIZE]={78, 80, 75, 82, 83};
declares a variable length array that may not be initialized in its declaration.
Instead you need to use an integral constant expression.
From the C Standard (6.6 Constant expressions).
6 An integer constant expression117) shall have integer type and shall
only have operands that are integer constants, enumeration constants,
character constants, sizeof expressions whose results are integer
constants, and floating constants that are the immediate operands of
casts. Cast operators in an integer constant expression shall only
convert arithmetic types to integer types, except as part of an
operand to the sizeof operator.
In this quote the term "integer constants"
means integer literals not objects declared with the qualifier const
.
You can declare the array for example the following way.
enum { SIZE = 5 };
int grades[SIZE]={78, 80, 75, 82, 83};
//...
Or alternatively you can introduce a macro like.
#define SIZE 5
//...
int grades[SIZE]={78, 80, 75, 82, 83};
//...
Or you could at first declare the array without specifying its size and then introduce the constant that specifiers its size as for example
int grades[]={78, 80, 75, 82, 83};
const size_t SIZE = sizeof( grades ) / sizeof( *grades );
Also these call of printf
.
printf("sum is at %p, or %lu and is %lf\n",
ptr_sum, ptr_sum, *ptr_sum);
printf("Grades are at %lu to %lu\n", grades, grades+5);
Are incorrect. You are trying to output a pointer using the conversion specifier lu
. You need to use the conversion specifier p
.
For example
printf("Grades are at %p to %p\n", ( void * )grades, ( void * )( grades+SIZE ));
Array size with const variable in C
Variable Length Arrays may have only automatic storage duration. VLAs were introduced in C99.
It is not allowed to declare a VLA with the static storage duration because the size of VLA is determinated at the run time (see below)
Before this Standard you can use either a macro like
#define SIZE 10
//...
int a[SIZE];
or a enumerator of an enumeration like
enum { SIZE = 10; }
//...
int a[SIZE];
By the way you may remove the const qualifier and just write
int size = 10;
instead of
const int size = 10;
(In C++ you have to use the const qualifier though in C++ there are no VLAs except that some compilers can have their own language extensions)
Take into account that the sizeof
operator for VLAs is calculated at the run-time instead of the compile-time.
Why we cannot create an array with a constant in c
In C:20
is a constant.unsigned int const size_of_list
is not a constant.
Title: "Why we cannot create an array with a constant in c" does not apply to this code.
const char* list_of_words[size_of_list] = {"Some", "Array"}; // Bad
An issue here (and the error message) is why a VLA cannot be initialized. That is answered here.
With a constant, array initialization works fine.
const char* list_of_words[20] = {"Some", "Array"}; // Good
Another issue is mistaking that const
makes an object a constant. It does not.
Alternative C code
int main(){
// unsigned int const size_of_list = 20;
#define size_of_list 20u
const char* list_of_words[size_of_list] = {"Some", "Array"};
for (unsigned int writing_index = 0; writing_index < size_of_list; writing_index ++)
;
return 0;
}
If you can specify the size in the array itself, then you can get it's size with the sizeof
operator. This may be better suited for having the compiler count up the size instead manual counting. When not using C99
VLAs, sizeof
also yields a compile-time constant.
#include <stddef.h> /* size_t */
int main(void) {
const char* list_of_words[] = {"Some", "Array"};
const char list_of_char[sizeof list_of_words
/ sizeof *list_of_words] = {'S','A'};
const size_t size_of_list
= sizeof list_of_words / sizeof *list_of_words;
for (size_t writing_index = 0;
writing_index < size_of_list; writing_index ++);
return 0;
}
In C, why can't a const variable be used as an array size initializer?
In C, a const
-qualified variable is not a constant expression1. A constant expression is something that can be evaluated at compile time - a numeric literal like 10
or 3.14159
, a string literal like "Hello"
, a sizeof
expression, or some expression made up of the same like 10 + sizeof "Hello"
.
For array declarations at file scope (outside the body of any function) or as members of struct
or union
types, the array dimension must be a constant expression.
For auto
arrays (arrays declared within the body of a function that are not static
), you can use a variable or expression whose value isn't known until runtime, but only in C99 or later.
- C++ is different in this regard - in that language, a
const
-qualified variable does count as a constant expression.
Why are those definitions not legal in C?
suppose you have
int a = 42;
const int *b = &a;
now *b
is const
ie read-only. You are not allowed to change *b
without casting the const
away (thanks Eric Postpischil)
// *b = -1; // not allowed
a = -1;
printf("%d\n", *b); // print -1
The point is: the value of a const
qualified object may change. A constant value never changes.
Why am I being allowed to use a const qualified variable as an array size in C?
c99
support variable length arrays but c90
does not support variable length arrays, you can see this more clearly if you are using gcc
and try to compile with these arguments:
gcc -std=c89 -pedantic
this will give you the following warning:
warning: ISO C90 forbids variable length array ‘y’ [-Wvla]
but if you compile using c99
it is perfectly fine:
gcc -std=c99 -pedantic
As pointed out by John Bode as of the 2011 C standard variable length arrays(VLA
) are now optional. Here is a Dr Dobbs article on VLA and also a link to the gcc
docs as pointed out by Wayne Conrad.
is defining size of arrays as a variable enter by user legal?
Variable-length arrays (VLAs) are legal from C99 onwards, although some compilers like GCC will allow them as an extension in older versions too. From C11 onwards, compilers are no longer required to support VLAs and will define __STDC_NO_VLA__
as 1
if they don't support it.
VLAs are inherently risky: either you know the maximum size of your data beforehand, in which case you can allocate a fixed-length array, or you don't, in which case you run the risk of overflowing the stack.
It's worth noting that in C++, variable-length arrays were never part of the standard.
Related Topics
How to Use Setenv() to Export a Variable in C++
Generate Include File Name in a MACro
Private Inheritance VS Composition:When to Use Which
Why Statements Cannot Appear at Namespace Scope
Assembly Adc (Add with Carry) to C++
Disable Eclipse's Error Discovery. (Codan False Positives)
Why Void_T Doesnt Work in Sfinae But Enable_If Does
Why Do Reference Type Members Cause Implicitly-Declared Copy Assignment Operator to Be Deleted
How to Avoid Including Class Implementation Files
Why Does This If Condition Fail for Comparison of Negative and Positive Integers
Is There Any Reason to Use C Instead of C++ for Embedded Development