What does `int const a[5]` really mean?

2019-02-25 04:54发布

Consider the following array declaration:

int const a[5];

From the semantic standpoint of the language, is it exactly equivalent to const int a[5]? Assuming that is the case, both declarations would essentially read like "a is an array of 5 constant ints".

The alternative way to read the first declaration would be "a is a constant array of 5 ints".

Obviously, both of the statements logically imply that the whole array is constant; if an array consists of 5 constant ints, then the entire array is constant. Alternatively, if the whole array is constant, then all of its values are also constant.

I am aware that the notion of a "constant array" is a bit meaningless since arrays are not modifiable lvalues (that is, they cannot appear on the left side of an assignment). However, are there any circumstances under which these two declarations would yield different behaviour?

(Cdecl.org rejects the first declaration as a syntax error, while most current compilers accept it.)

EDIT:

The linked duplicate asks whether the order of const matters for ordinary variables. With arrays, it is a bit more confusing, so I don't consider this a duplicate.

2条回答
成全新的幸福
2楼-- · 2019-02-25 05:00

I put this together:

#include <stdio.h>

int main()
{
    int const a[5];
    const int b[5];
    int c[5];

    a[0] = 1;
    b[0] = 2;
    c = a;
    c = b;
}

And gcc (4.1.2) spit out this:

gcc -o /tmp/x2 /tmp/x2.c
/tmp/x2.c: In function ‘main’:
/tmp/x2.c:9: error: assignment of read-only location
/tmp/x2.c:10: error: assignment of read-only location
/tmp/x2.c:11: error: incompatible types in assignment
/tmp/x2.c:12: error: incompatible types in assignment

So at least based on this there doesn't appear to be any distinction.

查看更多
你好瞎i
3楼-- · 2019-02-25 05:05

is it exactly equivalent to const int a[5]

Yes, it is.

The alternative way to read the first declaration would be "a is a constant array of 5 ints".

Not really. Your declaration, as written, applies const to array elements specifically. In order to apply the const to the array itself (as opposed to applying it to the array elements), you'd have to do something like

int (const a)[5];

but such declaration is syntactically invalid in C.

An indirect attempt to apply const to the array itself can be made through an intermediate typedef

typedef int A[5];
const A a;

but in this case, per language rules, the const qualifier "falls through" to array elements and the whole thing is just equivalent to

const int a[5];

Note, again, that const A a; above is not immediately equivalent to const int a[5];. It is actually equivalent to the aforementioned int (const a)[5]; (!). (It is a legal way to sneak int (const a)[5]; past compiler's defenses.) But that int (const a)[5]; is very-short lived - it gets immediately transformed into const int a[5]; by the compiler.

if an array consists of 5 constant ints, then the entire array is constant. Alternatively, if the whole array is constant, then all of its values are also constant.

Well, that is not entirely true. C language does differentiate between the array object itself and its elements. Conceptually, these are different entities. For example, as you noted yourself, the language spec says that arrays are non-modifiable lvalues. This, of course, does not prevent array elements to be modifiable.

This conceptual distinction between array as a whole and individual array elements, combined with the "fall through" behavior for const is exactly what leads to the following unpleasant situation

typedef int A[5];
A a;
const A *p = &a; // ERROR!!!

i.e. it breaks the "normal" const-correctness rule that allows us to initialize const T * pointers with T * values. (C++ deliberately updated it const-correctness rules to make the above code to behave "as expected", but C insists on rejecting it.)

查看更多
登录 后发表回答