3

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.

Blagovest Buyukliev
  • 42,498
  • 14
  • 94
  • 130
  • `const` applies to the type to it's left, unless it's the first in the declaration, in which case it applies to the right. So the both are equivalent. – bolov Jul 14 '15 at 17:07
  • 1
    Possibly a duplicate of http://stackoverflow.com/questions/7633776/constant-array-of-constant-objects? Regardless, this doesn't really mean anything. The `5` is already a constant here. When using `const int a[5];` it would give you a constant array in `C++`. Note that this does not work (correctly) in `C`! So for C it's pretty much ignored. – Wolph Jul 14 '15 at 17:08
  • 2
    They are the same. http://stackoverflow.com/questions/162480/const-int-vs-int-const-as-function-parameter-in-c-and-c – rlbond Jul 14 '15 at 17:08
  • 2
    "The 5 is already a constant here." -- irrelevant. "this doesn't really mean anything" -- wrong. " Note that this does not work (correctly) in C!" -- wrong. "So for C it's pretty much ignored." -- wrong. You misunderstand the question you cite (which is different from this) and Kerrick SB's answer. – Jim Balter Jul 14 '15 at 19:31
  • 3
    "However, are there any circumstances under which these two declarations would yield different behaviour?" -- the keyword order is a matter of *syntax* -- it has no bearing on the semantics. "Cdecl.org rejects the first declaration as a syntax error" -- then it's broken. – Jim Balter Jul 14 '15 at 19:35
  • 2
    C declarations are read inside out. So this says that `a` is an array of 5 const ints. Changing the order says that `a` is an array of 5 int consts, which is meaningless, but C allows you to put const first because the language designers were confused and did their best to spread that confusion. – Jim Balter Jul 14 '15 at 19:37

2 Answers2

12

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.)

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
1

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.

dbush
  • 205,898
  • 23
  • 218
  • 273