herbertF wrote:
Hi guys,
In a program (not my own) I encountered the declaration of a constant
pointer to an array consisting of two other const pointers to arrays.
Not quite sure why they do it so complicated, but is it legal? Most
compilers accept it, but one doesn't recognize the rhs as a constant.
What are the requirements for the rhs in the declaration of a const
pointer? Is the following program legal C?
int main(int argc, char *argv[]) {
const char *a[] = {"A"};
const char *b[] = {"B"};
const char **z[] = {a, b}; /* this is the statement in question */
return (0);
}
The error message is
"t.c", line 4: error: initialization: constant expression is expected
for variable: `z'
The complaining compiler is correct: `a' and `b' are not
constant expressions.
Despite the spelling, `const' is not
"constant."
If you think about it in a wider context, you'll see why
`a' and `b' are not constant. Here's a recursive function
with a similar construct, to help show what's happening:
void func(int x) {
const char *a[] = { "A", "B" };
if (0 <= x && x < 2) {
a[x] = "X";
printf ("func(%d): a[0] = %s, a[1] = %s\n",
x, a[0], a[1]);
func (x + 1);
printf ("func(%d): a[0] = %s, a[1] = %s\n",
x, a[0], a[1]);
}
else {
printf ("func(%d): nothing to do\n", x);
}
}
If you call this function with `func(0)', the output will be
func(0): a[0] = X, a[1] = B
func(1): a[0] = A, a[1] = X
func(2): nothing to do
func(1): a[0] = A, a[1] = X
func(0): a[0] = X, a[1] = B
This shows that two different `a' arrays exist: one in
the outer func(0) invocation, and another in the inner func(1).
You can see that there must be more than one `a[]' because
when the outer func(0) executes `a[0] = "X"' the value of `a[0]'
in the inner func(1) is not affected; likewise when the inner
func(1) sets `a[1] = "X"' it does not change `a[1]' in the
outer func(0). Each `a[]' array comes into existence when its
invocation of func() begins, and ceases to exist when its own
func() returns. Thus, even though `a' is just one identifier,
it designates different array objects at different times and
is therefore not a constant.
If you changed the function to declare the array as
static const char *a[] = { "A", "B" };
you would get a different output altogether:
func(0): a[0] = X, a[1] = B
func(1): a[0] = X, a[1] = X
func(2): nothing to do
func(1): a[0] = X, a[1] = X
func(0): a[0] = X, a[1] = X
In this case there is only one `a[]' array, and any changes
made to it in one func() invocation are seen in the other. The
lifetime of this single `a[]' is no longer tied to the execution
of its containing block; this `a[]' comes into existence before
the program starts executing and continues to exist until the
program terminates. In this case, `a' *is* a constant, because
the identifier refers to just one object for the entire time the
program is running. If the one-and-only-one semantics make sense
for your original program, perhaps the cure is to add the `static'
qualifier.
By the way, the non-complaining compilers are not in error.
A compiler is *permitted* to allow non-constant initializers in
addition to the constant initializers required by the Standard.
--
Er*********@sun .com