David Brown said:
On 07/04/14 17:52, BartC wrote:
[On the distinction between an actual constant, a named actual constant,
and
a variable that may or may not have a read-only attribute]
Yes, we should forget about these distinctions. They are not true or
realistic anyway, so why try to pretend that they are?
Remember, a C compiler is /not/ a translator - it does not translate C
source code into assembly. It takes a /description/ or /specification/
of a task, written in the more-or-less carefully defined language C, and
generates object code that will have the same /visible/ effect as the
specified task.
The distinction can be there in the /language/. Clearly not directly in C
because it doesn't have such a language construct, but some people who want
to code would like to have it because it makes certain things obvious and
not a consequence of a whim of a compiler writer.
With C, you can write 5678, but not &5678.
OK...
You can declare a variable xyz, and write as xyz to obtain the value, or as
&xyz to obtain its name (ie. a constant pointer value).
OK...
But note that xyz will not necessarily have an address unless you ask
for one (with &) and make use of that address. Local variables
typically stay in registers or are optimised away completely - they only
naturally have an address if the register set overflows onto the stack
(or if you force them to have an address using &).
And "static const" objects will not have an address or allocated memory
unless you ask for the address, or if a specific memory location gives
the most efficient code.
Why can't I declare abc as a synonym for 5678, but be stopped from writing
&abc? After all I can used #define or enum to declare abc, with some
limitations, and I can't write &abc then either.
I don't know why you would want this. It is not exactly a common typo -
so the way to stop yourself from writing &abc is simply don't write it.
Instead of a simple, logical extension to allow such a declaration,
where it
will be completely obvious what it is and what it can do, you instead
propose using a *variable* for the purpose, which so many issues associated
with it that I hardly know where to start! But I will have a go:
A "const" is not a variable - it is a constant object. So instead of
introducing some sort of new type of constant to the language, I would
rather take the existing const concept and extend it slightly (as it is
in C++) to cover the remaining needs for constants. That is far
simpler, clearer and easier than having a new type of constant - and it
already exists in C++.
o You expect users to apply a 'read-only' attribute to a /variable/, as a
hint to a compiler, so that it can pick up its initialisation value, if
there is one, and treat that as though it is a simple named constant. That
is going around the houses a little!
"const" is not a hint to the compiler about variables - it is a specific
direction that this object will be constant, and will never be changed.
(It is /possible/ to do so using casts, but the result is clearly
undefined behaviour, and cannot be achieved by accident due to the
explicit casts needed, and all the compiler error messages and/or
diagnostic warnings.)
I think you are mixing up the use of "const" in definitions such as
"static const int xyz = 123;", and its use in function arguments
(especially for pointers), such as "size_t strlen(const char* s)".
With the "const" declaration, you are telling the compiler that the
object will /never/ change value after its definition - so it can
happily use the initialisation value directly in code. For externally
defined constants, the compiler does not know the initialisation value -
it is forced to put the constant into memory so that other modules can
access it. But the memory can be read-only memory, and the compiler can
rely on the unchanging nature of the object. For "static const"
objects, the compiler does not have to put it into memory, but can use
the initialisation value directly as a compile-time fixed value. It is
a mere quirk of C language definitions that disallow the use of static
consts for things like array sizes.
When you use the const qualifier in a function argument, like
"strlen(const char* s)", you are telling the compiler that you will not
change anything through the pointer "s". It is not a hint - it is a
promise, and the compiler will hold you to it (with error messages) and
can take advantage of the knowledge that the data will be unchanged.
o It is necessary to use either 'static const int' or 'const int', although
I'm not sure what the difference is between them (that with static
const, it
can only be initialised to a constant expression)?
You are arguing for language extensions, and you don't even understand
the basics of C as it is?
At file level (i.e., not inside a function), "static" objects and
functions are local to the file - they have no external linkage, and
other compilation units cannot refer to them. Unless the objects escape
because you take their address and pass it on to another module through
function calls, then the compiler knows everything about the "static"
object's usage during compilation. In the case of a "static const", if
the initialisation value can be used directly in the code then it does
not need to make a memory location for the constant object. In the case
of functions, the compiler can do more optimisation or inlining because
it does not have to follow standard calling conventions.
Functions and objects that are not "static" have external linkage -
other modules can refer to them by name, so they must follow standard
calling conventions and memory placement (unless you are using link-time
optimisations, of course).
o 'static const int' doesn't need an initialisation value! (Presumably this
is then set to zero, but for a mechanism designed to define constant
values,
this is a bigger sin that omitting an explicit type.) ('const int' doesn't
need one either, and the value then is undefined.)
"const" objects, like variables, are initialised to 0 if you don't give
an explicit initialisation.
o 'const int' can be set to a runtime value! Presumably such a name cannot
be used as a simple named constant; or can it? The possibilities are
complicated.
"const" objects, like variables, must be initialised to compile-time
constants if they are at file scope (or function-local statics). When
they are used locally in functions, they don't exist until the function
is run - of course they can be initialised to any value that is
available when the function is run.
o 'const int' variables can, in certain circumstances, have their values
changed, so will differ from what the compiler thinks they might be.
No, they cannot be changed - any attempt to change them is undefined
behaviour.
(There is such as thing as a "volatile const" object, which is something
that might be changed outside of the program but which is illegal to
change from within the program. Such objects are never compile-time
constants.)
o '[static] const int]' exists now in C, yet cannot be used for
dimensioning
arrays or switch case-values. Maybe I missed something in the discussion,
but why is that? And what will change in future as apparently you are not
proposing any new syntax.
That is correct. I don't know why, other than for historical reasons,
[static] const objects cannot be used for things like array dimensions
in C. Such usage is legal in C++. And yes, I propose that they gain
the C++ features in C.
o I've just tried using a 'const int' value to define an array, and this
time it worked. Then I realised I was probably creating a VLA. I don't want
to inadvertently construct VLAs!
What is wrong with constructing a VLA? Do you know what a VLA actually
/is/? It is only legal in C to use a "const int" for the size of an
array when you are defining a function-local array, and you are correct
that it will be a VLA. But the reason the syntax for a VLA and a
fixed-size array is the same, is that they work in the same way and will
lead to virtually identical code. So it does not matter if the
function-local array is "fixed" size 100 from using a literal (or
#define, or enum), or VLA with a size given by a const or static const
that is initialised to 100.
So, full of difficulties, so I don't understand your objection to my very
simple proposal, which has few of those problems:
So, no difficulties at all - once you understand some basic C concepts.
o The name created is *not* a variable
Nor is a "const" or "static const".
o The initialisation value is mandatory, and *must* be evaluable at
compile-time
The initialisation value for a "const" and "static const" at file scope
must be compile-time constant, and will default to 0 if omitted.
Function-local constants can be initialised any way you like (and any
good compiler will warn you if you forget to initialise it).
o The value will *never* change, and you can never take its address
The value of a "const" or "static const" will /never/ change. You can
take its address if you want, or not if you don't want.
o It can be used to dimension non-VLA arrays, as switch case-values, and
can
be used to construct other such values
That's the only thing missing with C const today - and it should be
easily remedied by copying the feature from C++.
You can't propose an essential language feature and then say you need an
elite compiler to implement it properly!
Yes, I can propose an essential language feature (although I am not
doing so - I am proposing a small but useful addition to an existing
feature) and say good compilers will implement it well. Poor compilers
can easily implement constants as correct but inefficient code.