The term "variable" is not defined in the standard, except as part of
the phrase "variable length array". From the way it's used in the
standard, I've inferred that when used as a noun, it means "named
object", and every use in the standard is consistent with that meaning.
However, every use in the standard is also consistent with a more
restricted meaning that some people consider more consistent with it's
use in ordinary English, as something that can vary: "named object whose
definition is not const-qualified". His comment is more relevant if he's
referring to the more restricted definition.
In other words, I cannot protect the original values from being
altered? That may be a problem. Is there no way with C to make them
read-only?
Yes, you can add 'const' to the definition of such objects. That will
mean that diagnostics are mandatory if any part of the code makes a
naive attempt to modify them. The compiler has the option, after issuing
the mandatory diagnostic, of accepting your code and translating it into
a program; if you choose to run it, the behavior of that program is
undefined. The diagnostics can also be bypassed by use of a cast:
*(int*)AA_CONST = 3;
but such code also has undefined behavior.
Therefore, const-qualification doesn't actually guarantee that the
object can't be modified. Undefined behavior includes the possibility (
among infinitely many others) that the object's value could be modified.
However, mandatory diagnostics is the strongest guarantee C provides on
such matters; if it's not good enough, you'll have to find some other
language that provides a better guarantees.
The slight issue is that there seems to be no way in C to say which
symbols should be made available to other routines, i.e. which should
be exported, so if two programs are linked together each has access to
all the data in the other. I'd welcome correction if there is a
feature of C which allows this control.
C does not allow two programs to be linked together, so the issue never
comes up. Operating systems sometimes provide ways for programs to share
memory, for example if you're using a Unix-like system, you can use
mmap(), but the use of that function is outside the scope of the C
standard, and you'll get better answers to questions about it on
comp.unix.programmer. Other operating systems have similar features.
C does allow translation units to be linked together. I suspect that you
may be confusing translation units with programs. There can be at most
one main() function in any program (on freestanding systems, the
equivalent of main() may have a different name), but it can contain
multiple translation units. I'm most familiar with Unix-like systems, so
I'll use them as an example of how this usually works: you use a
compiler to convert a translation unit into an object file with an
extension of .o. Object files can be collected together into libraries
(with an extension of .a or .so). A linker is used to link one or more
..o files, whether stand-alone or extracted from a library, into a single
program.
Does that give you a better idea of what "program" means?
C does provide features that allow you to control whether or not an
identifier is shared between TUs. Every identifier has either internal
linkage, external linkage, or no linkage. Linkage applies only to
identifiers that identify objects or functions. Identifiers with
internal linkage identify the thing that they identify only within the
same translation unit where they are declared. Identifiers with external
linkage can be declared in one translation unit, and used within the
scope of that declaration to refer to things that might be defined in a
different translation unit. If your program has multiple definitions of
an identifier with external linkage, it has undefined behavior. If your
program actually uses the think identified by such an identifier, it has
undefined behavior unless it includes exactly one definition of the
identifier.
When you define a function or a file scope object, the identifier has
external linkage unless the 'static' keyword is used. Declarations of
functions and objects that have the 'extern' keyword do not define
anything, but merely make the corresponding identifier usable within the
scope of the declaration to refer to something defined with external
linkage using the same identifier in some other part of the program.
As a general rule, every identifier with external linkage (except
possibly "main") in your program should be declared in a header file
(with the 'extern' keyword if it identifies an object). That header file
should be #included in every translation unit where that identifier is
referred to - INCLUDING the one where the thing it identifies is
defined. This is not something that's required by the standard, it's
merely a good way to ensure that the thing is declared consistently
where it is used. The behavior of your program can be undefined if the
declarations are inconsistent between different translation units.