Why not const variables? In discussions about it, I see nearly everyone saying it's better to use const, yet C programmers seem to use #define all the time for simple constant integers.
[29] Newbie Questions / Answers ..Updated!.., C++ FAQ Lite
Printable View
Why not const variables? In discussions about it, I see nearly everyone saying it's better to use const, yet C programmers seem to use #define all the time for simple constant integers.
[29] Newbie Questions / Answers ..Updated!.., C++ FAQ Lite
C != C++, that's the simple answer.
const integers aren't considered constant expressions in C, so using it, for example, to set the size of an array may not work (it won't work under C90, but it would work in C99).
They also take up memory, unless the compiler somehow optimizes them away (though I don't think it's allowed to).
I don't know about that, but I doubt any global variable could be optimized out, in case some unforeseen file references it. Of course, static global variables probably could be optimized away.Quote:
They also take up memory, unless the compiler somehow optimizes them away (though I don't think it's allowed to).
The simple answer is what Elysia has already said: in C, "const" variables are not constant expressions. Seems strange, but that's the way it is.
No so sure I could see this as a significant "reason" either:
And the other ones are a little thin too IMO; this is presented as the reason "why the preprocessor is evil":Quote:
they don't create new "keywords" in your program.
Which seems to me more like a statement of fact rather than something that is inherently ungood or something. Like, it might have been better to say "be careful and use unique names with define". Also, the advantage of using the preprocessor (that it helps simplify and optimize compiling) is not mentioned.Quote:
Every #define macro effectively creates a new keyword in every source file and every scope until that symbol is #undefd. The preprocessor lets you create a #define symbol that is always replaced independent of the scope where that symbol appears.
Nonetheless, I regard the first, second and last as being reason enough to prefer the compiler over the preprocessor.Quote:
Originally Posted by MK27
He is just stating the corollary of the first and last points listed earlier.Quote:
Originally Posted by MK27
Rather, I think that it would have been better to add that one should be careful with macro names when macros are used, e.g., by adopting the naming convention of using fully capitalised names for macros.Quote:
Originally Posted by MK27
I suspect that it is, in part, tradition. There are certainly times when a macro is necessary, but I have seen a number of macros that could just as easily be variables. I've been guilty of using macros where they're not necessary, but I'm getting in the habit of changing. I especially like variables because they come with an explicit type (you can't always know what type an unadorned number will be, nor are there suffixes for all types). I'd much rather do this:
than this:Code:const size_t BLAH = 50;
As for not being able to optimize out, it's true that a compiler would have to keep a copy of the object around, but nothing stops it from replacing references to the variable with a constant value. After all, if another source file modifies the const object, you've got undefined behavior. My versions of gcc and icc do this, although clang doesn't.Code:#define BLAH ((size_t)50)
Plus if you're doing C99, you don't even need constant expressions for (local) array sizes anymore.
Is the C compiler allowed to make an assumption that the value of a const variable won't change and hence replace occurrences of that variable with its value (even though the variable itself isn't eliminated)?
Yes (unless it's also volatile). If it could change, there'd be no point in using const. While non-normative, footnote 112 in C99 6.7.3p3 makes this pretty clear:
For fun, this program can be used to see how a particular compiler reacts:Quote:
The implementation may place a const object that is not volatile in a read-only region of storage. Moreover, the implementation need not allocate storage for such an object if its address is never used.
On my system, gcc, clang, and sunstudio all segfault, presumably because "a" is read-only. icc spits out the value 3, indicating that it treated "a" as a macro, more or less.Code:#include <stdio.h>
static const int a = 3;
int main(void)
{
int *b;
b = (int *)&a;
*b = 10;
printf("%d\n", a);
return 0;
}
Then why not use a macro in the first place?
Incompatibilities Between ISO C and ISO C++
const in C and C++ mean very different things.
A const in C is just a variable with an attribute of "warn me if I try to modify this".
For one thing, you can't do this in C.
The only way to give a symbolic name to a numeric constant in C is to use #define.Code:const int size = 10;
int myarray[size];
This of course is perfectly legal (and encouraged) in C++.
Oh, and the link is required reading for anyone thinking that C++ is a simple superset of C.
> A const in C is just a variable with an attribute of "warn me if I try to modify this".
While that's true for type "pointer to const something", it's not true for objects that have const, like "const int" or "const pointer to something". In that case, if you modify it directly, that would be an error, and if you try to modify it through a pointer, it's undefined behavior.
You can't do it in C90, but you can do it in C99, which GCC conveniently supports.
I understand now. Gcc's default mode is "gnu89" which supports C99 features. In c89 mode:Thanks for all the answers to my original question as well.Quote:
warning: ISO C90 forbids variable length array ‘myarray’