I'm trying to pass values of two variables to be the dimension of the students_grades_db array, but it doesn't work and I don't know why, as both are constant variables.
const int number_students = 4;
const int number_of_notes = 4;
float students_grades_db[number_students][number_of_notes] = {0};
It doesn't work :(
A global array declaration must have constant expressions for index sizes. References to variables (even const variables) are not constant expressions, so can't be used.
You can instead use preprocessor macros that expand to constant literals:
#define number_of_students 4
#define number_of_notes 4
If you declare an array outside a function at file scope, it will then get static storage duration. All variables with static storage duration must have compile-time constants as initializers and if they are arrays, the array sizes must also be compile-time constants.
This means that the size has to be something like an integer constant 123 or an expression containing only integer constants.
The const keyword, non-intuitively, does not make something a compile-time constant, it only makes something read-only. C and C++ are different here, you code would work in C++.
Possible solutions:
Move students_grades_db inside a function. Then you can declare array sizes using any kind of expression, including common int variables. You probably shouldn't declare that array as "global" anyhow.
Or swap out your constants for #define number_students 4.
I am trying to define a 'variable' with a macro which can later be used as a constant value ...I have now run out of ideas and wondering if anyone can tell me if I've missed anything:
This is what I originally coded, but C does not recognise 'name' as a constant
qv. compile error C2099: initializer is not a constant
#define DECL(name,value) static const unsigned long int name = value
DECL(FOO, 0xFFFFFFFF)
My next attempt was to write a macro that would #define the value for me ...But the compiler complains about the embedded # : "error: '#' is not followed by a macro parameter"
qv. Escaping a # symbol in a #define macro?
#define DECL(name,value) #define name (value)UL
DECL(FOO, 0xFFFFFFFF)
At ^-this-^ link, ybungalobill claims v-this-v works ... but it doesn't
#define DECL(hash, name, value) hash define name (value)UL
DECL(#, FOO, 0xFFFFFFFF)
I managed to get my code to compile with this enum trick (inspired by the first link) ...it works on my computer, but as this issue is ultimately about creating portable code [portable between languages as well as platforms!] I am worried about the sizeof and signed'ness of the value. qv. What is the size of an enum in C?
#define DECL(name,value) enum { name = value } ;
DECL(FOO, 0xFFFFFFFF)
Here are some lines of code which may use the above FOO value:
int array[FOO];
static const unsigned long int BAR = FOO + 1 ;
int main (void) {
unsigned long int var1 = FOO;
printf("%d - %d\n", FOO, sizeof(FOO));
}
A macro definition cannot include preprocessor directives, so you can't #define something that expands to another #define.
The const keyword in C doesn't mean "constant"; it means "read-only". A "constant" expression is one that can be evaluated at compile time. A const object is one whose value may not be modified. For example:
const int r = rand();
r is const, meaning you can't modify it after it's been initialized, but it's not "constant" (it can't be, since the value returned by rand() can't be determined until run time).
Using a constant expression as the initializer doesn't change this. (It does in C++.)
The usual way to define a named constant in C is to define it directly as a macro. For example, rather than
#define DECL(name,value) #define name (value)UL
DECL(FOO, 0xFFFFFFFF)
just write:
#define FOO 0xFFFFFFFFUL
For the special case of constants of type int, you can use an enum declaration:
enum { max = 1000 };
This defines an anonymous enumeration type and a constant max of that type. max is a constant of type int. It's defined that way for historical reasons; it would probably make more sense if max were of the enumeration type (as it is in C), but it isn't.
Your issue is not related to macros in any way.
I am trying to define a 'variable' [...] which can later be used as a constant value
You cannot do this in the sense that this variable can be use as an initialiser.
It would stay a variable.
For further reading: Error "initializer element is not constant" when trying to initialize variable with const
Which one is better to use among the below statements in C?
static const int var = 5;
or
#define var 5
or
enum { var = 5 };
It depends on what you need the value for. You (and everyone else so far) omitted the third alternative:
static const int var = 5;
#define var 5
enum { var = 5 };
Ignoring issues about the choice of name, then:
If you need to pass a pointer around, you must use (1).
Since (2) is apparently an option, you don't need to pass pointers around.
Both (1) and (3) have a symbol in the debugger's symbol table - that makes debugging easier. It is more likely that (2) will not have a symbol, leaving you wondering what it is.
(1) cannot be used as a dimension for arrays at global scope; both (2) and (3) can.
(1) cannot be used as a dimension for static arrays at function scope; both (2) and (3) can.
Under C99, all of these can be used for local arrays. Technically, using (1) would imply the use of a VLA (variable-length array), though the dimension referenced by 'var' would of course be fixed at size 5.
(1) cannot be used in places like switch statements; both (2) and (3) can.
(1) cannot be used to initialize static variables; both (2) and (3) can.
(2) can change code that you didn't want changed because it is used by the preprocessor; both (1) and (3) will not have unexpected side-effects like that.
You can detect whether (2) has been set in the preprocessor; neither (1) nor (3) allows that.
So, in most contexts, prefer the 'enum' over the alternatives. Otherwise, the first and last bullet points are likely to be the controlling factors — and you have to think harder if you need to satisfy both at once.
If you were asking about C++, then you'd use option (1) — the static const — every time.
Generally speaking:
static const
Because it respects scope and is type-safe.
The only caveat I could see: if you want the variable to be possibly defined on the command line. There is still an alternative:
#ifdef VAR // Very bad name, not long enough, too general, etc..
static int const var = VAR;
#else
static int const var = 5; // default value
#endif
Whenever possible, instead of macros / ellipsis, use a type-safe alternative.
If you really NEED to go with a macro (for example, you want __FILE__ or __LINE__), then you'd better name your macro VERY carefully: in its naming convention Boost recommends all upper-case, beginning by the name of the project (here BOOST_), while perusing the library you will notice this is (generally) followed by the name of the particular area (library) then with a meaningful name.
It generally makes for lengthy names :)
In C, specifically? In C the correct answer is: use #define (or, if appropriate, enum)
While it is beneficial to have the scoping and typing properties of a const object, in reality const objects in C (as opposed to C++) are not true constants and therefore are usually useless in most practical cases.
So, in C the choice should be determined by how you plan to use your constant. For example, you can't use a const int object as a case label (while a macro will work). You can't use a const int object as a bit-field width (while a macro will work). In C89/90 you can't use a const object to specify an array size (while a macro will work). Even in C99 you can't use a const object to specify an array size when you need a non-VLA array.
If this is important for you then it will determine your choice. Most of the time, you'll have no choice but to use #define in C. And don't forget another alternative, that produces true constants in C - enum.
In C++ const objects are true constants, so in C++ it is almost always better to prefer the const variant (no need for explicit static in C++ though).
The difference between static const and #define is that the former uses the memory and the later does not use the memory for storage. Secondly, you cannot pass the address of an #define whereas you can pass the address of a static const. Actually it is depending on what circumstance we are under, we need to select one among these two. Both are at their best under different circumstances. Please don't assume that one is better than the other... :-)
If that would have been the case, Dennis Ritchie would have kept the best one alone... hahaha... :-)
In C #define is much more popular. You can use those values for declaring array sizes for example:
#define MAXLEN 5
void foo(void) {
int bar[MAXLEN];
}
ANSI C doesn't allow you to use static consts in this context as far as I know. In C++ you should avoid macros in these cases. You can write
const int maxlen = 5;
void foo() {
int bar[maxlen];
}
and even leave out static because internal linkage is implied by const already [in C++ only].
Another drawback of const in C is that you can't use the value in initializing another const.
static int const NUMBER_OF_FINGERS_PER_HAND = 5;
static int const NUMBER_OF_HANDS = 2;
// initializer element is not constant, this does not work.
static int const NUMBER_OF_FINGERS = NUMBER_OF_FINGERS_PER_HAND
* NUMBER_OF_HANDS;
Even this does not work with a const since the compiler does not see it as a constant:
static uint8_t const ARRAY_SIZE = 16;
static int8_t const lookup_table[ARRAY_SIZE] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; // ARRAY_SIZE not a constant!
I'd be happy to use typed const in these cases, otherwise...
If you can get away with it, static const has a lot of advantages. It obeys the normal scope principles, is visible in a debugger, and generally obeys the rules that variables obey.
However, at least in the original C standard, it isn't actually a constant. If you use #define var 5, you can write int foo[var]; as a declaration, but you can't do that (except as a compiler extension" with static const int var = 5;. This is not the case in C++, where the static const version can be used anywhere the #define version can, and I believe this is also the case with C99.
However, never name a #define constant with a lowercase name. It will override any possible use of that name until the end of the translation unit. Macro constants should be in what is effectively their own namespace, which is traditionally all capital letters, perhaps with a prefix.
#define var 5 will cause you trouble if you have things like mystruct.var.
For example,
struct mystruct {
int var;
};
#define var 5
int main() {
struct mystruct foo;
foo.var = 1;
return 0;
}
The preprocessor will replace it and the code won't compile. For this reason, traditional coding style suggest all constant #defines uses capital letters to avoid conflict.
It is ALWAYS preferable to use const, instead of #define. That's because const is treated by the compiler and #define by the preprocessor. It is like #define itself is not part of the code (roughly speaking).
Example:
#define PI 3.1416
The symbolic name PI may never be seen by compilers; it may be removed by the preprocessor before the source code even gets to a compiler. As a result, the name PI 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 3.1416, not PI. If PI were defined in a header file you didn’t write, you’d have no idea where that 3.1416 came from.
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.
Solution:
const double PI = 3.1416; //or static const...
I wrote quick test program to demonstrate one difference:
#include <stdio.h>
enum {ENUM_DEFINED=16};
enum {ENUM_DEFINED=32};
#define DEFINED_DEFINED 16
#define DEFINED_DEFINED 32
int main(int argc, char *argv[]) {
printf("%d, %d\n", DEFINED_DEFINED, ENUM_DEFINED);
return(0);
}
This compiles with these errors and warnings:
main.c:6:7: error: redefinition of enumerator 'ENUM_DEFINED'
enum {ENUM_DEFINED=32};
^
main.c:5:7: note: previous definition is here
enum {ENUM_DEFINED=16};
^
main.c:9:9: warning: 'DEFINED_DEFINED' macro redefined [-Wmacro-redefined]
#define DEFINED_DEFINED 32
^
main.c:8:9: note: previous definition is here
#define DEFINED_DEFINED 16
^
Note that enum gives an error when define gives a warning.
The definition
const int const_value = 5;
does not always define a constant value. Some compilers (for example tcc 0.9.26) just allocate memory identified with the name "const_value". Using the identifier "const_value" you can not modify this memory. But you still could modify the memory using another identifier:
const int const_value = 5;
int *mutable_value = (int*) &const_value;
*mutable_value = 3;
printf("%i", const_value); // The output may be 5 or 3, depending on the compiler.
This means the definition
#define CONST_VALUE 5
is the only way to define a constant value which can not be modified by any means.
Although the question was about integers, it's worth noting that #define and enums are useless if you need a constant structure or string. These are both usually passed to functions as pointers. (With strings it's required; with structures it's much more efficient.)
As for integers, if you're in an embedded environment with very limited memory, you might need to worry about where the constant is stored and how accesses to it are compiled. The compiler might add two consts at run time, but add two #defines at compile time. A #define constant may be converted into one or more MOV [immediate] instructions, which means the constant is effectively stored in program memory. A const constant will be stored in the .const section in data memory. In systems with a Harvard architecture, there could be differences in performance and memory usage, although they'd likely be small. They might matter for hard-core optimization of inner loops.
Don't think there's an answer for "which is always best" but, as Matthieu said
static const
is type safe. My biggest pet peeve with #define, though, is when debugging in Visual Studio you cannot watch the variable. It gives an error that the symbol cannot be found.
Incidentally, an alternative to #define, which provides proper scoping but behaves like a "real" constant, is "enum". For example:
enum {number_ten = 10;}
In many cases, it's useful to define enumerated types and create variables of those types; if that is done, debuggers may be able to display variables according to their enumeration name.
One important caveat with doing that, however: in C++, enumerated types have limited compatibility with integers. For example, by default, one cannot perform arithmetic upon them. I find that to be a curious default behavior for enums; while it would have been nice to have a "strict enum" type, given the desire to have C++ generally compatible with C, I would think the default behavior of an "enum" type should be interchangeable with integers.
A simple difference:
At pre-processing time, the constant is replaced with its value.
So you could not apply the dereference operator to a define, but you can apply the dereference operator to a variable.
As you would suppose, define is faster that static const.
For example, having:
#define mymax 100
you can not do printf("address of constant is %p",&mymax);.
But having
const int mymax_var=100
you can do printf("address of constant is %p",&mymax_var);.
To be more clear, the define is replaced by its value at the pre-processing stage, so we do not have any variable stored in the program. We have just the code from the text segment of the program where the define was used.
However, for static const we have a variable that is allocated somewhere. For gcc, static const are allocated in the text segment of the program.
Above, I wanted to tell about the reference operator so replace dereference with reference.
We looked at the produced assembler code on the MBF16X... Both variants result in the same code for arithmetic operations (ADD Immediate, for example).
So const int is preferred for the type check while #define is old style. Maybe it is compiler-specific. So check your produced assembler code.
I am not sure if I am right but in my opinion calling #defined value is much faster than calling any other normally declared variable (or const value).
It's because when program is running and it needs to use some normally declared variable it needs to jump to exact place in memory to get that variable.
In opposite when it use #defined value, the program don't need to jump to any allocated memory, it just takes the value. If #define myValue 7 and the program calling myValue, it behaves exactly the same as when it just calls 7.
I am making a pong clone to test a SDK... It is some years that I don't C.
Anyway, I tried to do this in the const setup phase:
const int SCREEN_W = 480;
const int SCREEN_H = 480;
const int PLAYER_H_WIDTH = 50;
const int PLAYER_H_HEIGHT = 12;
const int BUFFER = 14;
const int LEFT_BUFFER = PLAYER_H_WIDTH+BUFFER;
const int RIGHT_BUFFER = SCREEN_W-LEFT_BUFFER;
except the compiler throws a error at LEFT_BUFFER and RIGHT_BUFFER lines, thus making me wonder, why?
If the answer is "because the standard says so" I still want to know why (why the standard says so?)
EDIT because of comments:
haccks noticed that those lines inside a function (like, main(){}) do compile, while on file scope they don't. I also ask, why?
Also the specific GCC (actually MingW) error is: initializer element is not constant
An initializer for an object declared with static storage duration (outside any function, or inside a function with the static keyword) must be a constant expression, or must contain only constant expressions.
This declaration:
const int PLAYER_H_WIDTH = 50;
does not make PLAYER_H_WIDTH a constant expression. The keyword const really doesn't mean "constant" (i.e., able to be evaluated at compile time); it means "read-only".
So when you declare:
const int LEFT_BUFFER = PLAYER_H_WIDTH+BUFFER;
you're trying to initialize LEFT_BUFFER with a non-constant expression.
Reference: ISO C standard, 2011 edition, section 6.7.9 paragraph 4:
All the expressions in an initializer for an object that has static or
thread storage duration shall be constant expressions or string
literals.
To illustrate the difference between const and constant, this:
const int r = rand();
is a perfectly valid declaration, as long as it's not at file scope. The object (I don't want to call it a "variable") r is const (i.e., read-only), but not constant (i.e., its value can't be determined at compile time).
That declaration cannot appear outside any function because of C's execution model, which doesn't allow user code to be executed before main is entered.
C++ does make such objects constant if the initializer is constant and of integer type; C does not. The rule in C++ requires a bit more work by the compiler; it make the determination of whether an object's name is a constant expression dependent on the the form of its initializer. I'm not sure why C hasn't adopted the C++ rule; probably the committee didn't feel it was worthwhile (remember that any new feature imposes a burden on every compiler implementer).
As a workaround, you can either use the preprocessor:
#define PLAYER_H_WIDTH 50
/* ... */
#define LEFT_BUFFER (PLAYER_H_WIDTH+BUFFER)
or you can use a slightly ugly hack with enum:
enum { PLAYER_H_WIDTH = 50 };
enum { LEFT_BUFFER = PLAYER_H_WIDTH+BUFFER };
The latter works only for constants of type int. The trick is that an enum declaration creates an enumeration type, but the enumerators are still of type int.
Your question title shows that you've been misled by some confusion. It has nothing to do with a + b or a - b. You will get the same error if you just do
const int LEFT_BUFFER = BUFFER;
without any + or -.
The problem is that none of the names you defined are "constants", meaning that they cannot form constant expressions. For example, SCREEN_W is not a constant.
In C language the term "constant" applies to literal values (like 42) and to enum constants. Variables declared as const are not "constants" in C language. You can call them "const variables" if you want, but you will never be able to use them where true constants are required.
That is just the way it is in C. That is how it has always been in C. If you want to declare a manifest constant in C language, use #define or enum. Don't attempt to use const. const has some pleasant properties (compared to #define), but the fact that const does not produce true constants in C severely limits the usability of const for declaring manifest constants.
Your original example actually demonstrates the issue. Objects with static storage duration require constant initializers in C. Since your PLAYER_H_WIDTH, BUFFER etc. are not constants, you cannot use them as initializers for objects with static storage duration. And, again, the problem has nothing to do with + or -, it is present even in
const int LEFT_BUFFER = BUFFER;
declaration.
If you transfer these lines into local scope, your objects will no longer have static storage duration. They will become local variables. The aforementioned restriction does not apply to local variables, which is why your declarations will compile without any problems. However, if you add the keyword static to the above declarations, the error will reappear even in local scope.
C's constant is not actually a "constant" as we expected. It is an indicator to the compiler that the variable's content could not be changed. The initialize needs to be constant expressions or string literals.
The closest thing to a constant in C is using enum or #define, e.g.
enum {
SCREEN_W = 480,
SCREEN_H = 480,
PLAYER_H_WIDTH = 50,
PLAYER_H_HEIGHT = 12,
BUFFER = 14,
LEFT_BUFFER = PLAYER_H_WIDTH+BUFFER,
RIGHT_BUFFER = SCREEN_W-LEFT_BUFFER
};
I would use enum as far as I could.
use The #define directive preprocessor if you want to avoid this error !
const int SCREEN_W = 480;
const int SCREEN_H = 480;
const int PLAYER_H_WIDTH = 50;
const int PLAYER_H_HEIGHT = 12;
const int BUFFER = 14;
#define LEFT_BUFFER PLAYER_H_WIDTH + BUFFER
#define RIGHT_BUFFER SCREEN_W - LEFT_BUFFER
The #define directive is a preprocessor directive; the preprocessor replaces those macros by their body before the compiler even sees it. Think of it as an automatic search and replace of your source code.
But a constant defined with the const qualifier is best thought of as an unmodifiable variable. It has all the properties of a variable: it has a type, it has a size, it has linkage, you can take its address.
for this the compiler can't compile the assignment of const variable to another, because the assigned variable is not a constant expression.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
“static const” vs “#define” in c
I am going through the K&R book and this question came up. How to best decide whether something should be its own variable or be defined as a symbolic constant?
Suppose we're dealing with const int myNumber = 12; , which also can be #define MY_NUMBER 12 is there a rule of thumb one should follow when deciding which whether a variable needs to be created or symbolic constant used?
The real question is whether n should be a declared const object or a macro. (The question's title currently refers to "a variable or a symbolic constant".)
This:
const int myNumber = 12;
makes myNumber const but not constant. The const keyword means that you're not allowed to modify the object it applies to, but it doesn't make it constant. Switch labels, for example, must be constant; you can't write:
switch (n) {
case myNumber:
...
}
So if you need to use myNumber in a context that requires a constant expression, the above isn't going to work.
On the other hand, a macro:
#define MY_NUMBER 12
means that any use of MY_NUMBER is replaced by a literal 12, which is constant. A drawback of macros is that they're not scoped the way declared objects are; the name MY_NUMBER is visible from the definition to the end of the source file, which can cause conflicts. (Note that macro names are conventionally written in all-caps, specifically to draw attention to them.) In effect, the preprocessor, which is where macros are handled is another language tacked onto C.
For constants of type int, there's another trick you can use (I don't think K&R mention this):
enum { myNumber = 12 };
This creates an anonymous enumeration type, which you aren't actually going to use. myNumber is actually of type int, not of the enumeration type, and you can use it the same way you'd use the literal 12. You can even use an expression to define its value, as long as the expression is constant:
enum { myNumber = 3 * 4 };
(C++ has different rules. In C++, const int myNumber = 12; does make myNumber a constant expression -- and enumeration constants are of the enumerated type, not of type int.)
If you're hard-coding a constant like "2" ... then it's a candidate for symbolic parameter.
ADDENDUM:
You changed the question :)
Q: I am going through the K&R book and this question came up. How to
best decide whether something should be its own variable or be defined
as a symbolic parameter?
A: "Magic numbers" are bad. Use "#define SOME_MEANINGFUL_NAME 2" in preference to "2".
Q: Suppose were dealing with const int myNumber = 12; , which also can
be #define MY_NUMBER 12 is there a rule of thumb one should follow
when deciding which approach to take here?
A: If you're using C++ or C#, then you should probably use "const" in favor of "#define".