Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
In C, declaring an array size using a variable, even if it is a const
variable, is NOT allowed. Ex: this fails to compile in C:
#include <stdio.h>
const int SIZE = 2;
int a[SIZE];
int main()
{
a[0] = 1;
a[1] = 2;
printf("%i, %i", a[0], a[1]);
return 0;
}
Run this code in C.
Output:
$gcc -o main *.c
main.c:5:5: error: variably modified ‘a’ at file scope
int a[SIZE];
^
In C++, however, it runs just fine.
Run the above code in C++.
Output:
$g++ -o main *.cpp
$main
1, 2
To make it run in C, you must use #define
instead of a variable. ie:
This runs just fine in C OR C++:
#include <stdio.h>
#define SIZE 2
// const int SIZE = 2;
int a[SIZE];
int main()
{
a[0] = 1;
a[1] = 2;
printf("%i, %i", a[0], a[1]);
return 0;
}
Run this code in C.
So, in C++ I've almost always used a variable, rather than #define
, to declare my array sizes. I just make the array size variable const
and it's all good! Recently I started doing a lot of microcontroller programming in pure C, however, and when I ran into this error and figured out the problem, a senior developer told me it's bad practice to use anything but #define
-ed constants (or maybe hard-coded numbers) to declare array sizes.
Is this true? Is it bad practice in C++ to use const
variables instead of #define
when specifying array sizes? If so, why?
In C, apparently you're stuck with #define
: you have no other choice. But in C++ you clearly have at least 2 choices, so is one better than the other? Is there a risk to using one over the other?
Related:
- variably modified array at file scope in C
- static const vs #define <-- this is a solid question and very helpful. It is most definitely related to my question, but my question is NOT a duplicate because although they are both about const vs #define, my question is a very special case where one of the options doesn't even work in a language which is regularly considered to be a subset of C++. That's pretty unusual, and makes my question a more narrow subset which fits within the broad scope of this other question. Therefore, not a duplicate.
- https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es31-dont-use-macros-for-constants-or-functions
- "static const" vs "#define" vs "enum"
- https://en.wikipedia.org/wiki/Variable-length_array#C99
It would be good to follow Scott Meyer's advice in this matter. From his book "Effective C++":
Item 2: Prefer consts, enums, and inlines to #defines.
Summary of the item adapted to your example.
This Item might better be called “prefer the compiler to the preprocessor,”
because #define
may be treated as if it’s not part of the language
per se. That’s one of its problems.
When you do something like this,
#define SIZE 2
the symbolic name SIZE
may never be seen by compilers; it
may be removed by the preprocessor before the source code ever gets
to a compiler. As a result, the name SIZE
may not get entered
into the symbol table. This can be confusing if you get an error during
compilation involving the use of the constant, because the error message
may refer to 2
, not SIZE
. If SIZE
were
defined in a header file you didn’t write, you’d have no idea where that
2
came from, and you’d waste time tracking it down. This problem
can also crop up in a symbolic debugger, because, again, the name
you’re programming with may not be in the symbol table.
The solution is to replace the macro with a constant:
const double SIZE = 2; // uppercase names are usually for macros, hence the name change
As a language constant, SIZE
is definitely seen by compilers and
is certainly entered into their symbol tables.
✦ For simple constants, prefer const objects or enums to #defines.
✦ For function-like macros, prefer inline functions to #defines.
Also refer to "Item 3: Use const whenever possible." for more info on its usage and exceptions to its usage.
So to answer your question in the title:
No, it is NOT a bad practice to specify an array size using a variable instead of #define
in C++.
Because SIZE
was defined as a const
variable. In C, unlike C++ const
values are not true constants. They are stored in memory and can be referenced and modified indirectly (by modifying the contents in memory). That's why, in C++ there is const
that would allow const int SIZE = 2;
to work, but even const
is not enough in C.
C11-§6.7.9/3:
The type of the entity to be initialized shall be an array of unknown
size or a complete object type that is not a variable length array
type.
Preprocessor macro replace at compile time, that's why it's work fine.
Reference Link : https://stackoverflow.com/a/35162075/5612562
I like your question! C++ is evolving to a language where you no longer need #define
. Depending on the version, you can replace other constructs. Their are several reasons for this, including problems with IDEs, unexpected replacement of variable names of enum values with other constants, (Don't combine ERROR and ) and the absence of namespaces as this is all preprocessor replacement.
For this example, you create a C-style array, which requires a constant. Writing const int SIZE = 2
however does not create a constant, it creates a immutable variable. This can be used in a lot of ways and can be initialized with almost any code, including something you calculated from reading a file.
The thing you are searching for is constexpr
. The keyword that promotes your variable to a compile time constant and limits the initialization options to all code that can be executed at compile time. So: constants, calculations with them and constexpr functions that group these calculations.
If you want to know more about it, Google for constexpr (or use a different search engine).
Note C++11 is required for constexpr, C++14 is recommended when you want to write constexpr functions. For constexpr standard library functions, you'll have to wait C++20, if I remember well.
constexpr int SIZE = 2;
int a[SIZE];