Path: csiph.com!eternal-september.org!feeder.eternal-september.org!nntp.eternal-september.org!.POSTED!not-for-mail From: Keith Thompson Newsgroups: comp.lang.c Subject: Re: pedantic gcc and const 2D arrays Date: Wed, 08 Apr 2026 15:57:05 -0700 Organization: None to speak of Lines: 75 Message-ID: <87ldex2h8e.fsf@example.invalid> References: <20260409012107.00006dc5@yahoo.com> MIME-Version: 1.0 Content-Type: text/plain Injection-Date: Wed, 08 Apr 2026 22:57:10 +0000 (UTC) Injection-Info: dont-email.me; posting-host="4da677159a35e2be2e454ca34c4cf64d"; logging-data="4151979"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX19ErAviA22XVeO8zqDXRJlq" User-Agent: Gnus/5.13 (Gnus v5.13) Cancel-Lock: sha1:2yL5aeiZpxQH+mFkpK6T9UnLuSs= sha1:THICnWfUQXyMGYjtbUMhhQNdoLk= Xref: csiph.com comp.lang.c:397435 Michael S writes: > IIRC, this is my first on-topic post in comp.lang.c group. > As they say, nobody is perfect. > > // pedant_2d.c > int bar(const int a[5][42]) > { > return a[0][0]; > } > > int foo(int x) > { > int a[5][42]; > a[0][0] = 1; > return bar(a); > } > > // end of pedant_2d.c > > > $ gcc -std=c17 -pedantic -c pedant_2d.c > pedant_2d.c: In function 'foo': > pedant_2d.c:10:14: warning: invalid use of pointers to arrays with > different qualifiers in ISO C before C23 [-Wpedantic] 10 | return > bar(a); | ^ > > What does it mean ? This is an incomplete answer. Perhaps someone else can fill in some more details. Given the parameter declaration `const int a[5][42]`, a is of course a pointer, not an array. Specifically, it's of type `constint(*)[42])`, or "pointer to array 42 of const int". (The 5 is quietly ignored.) The argument `a` in the call (it might have been clearer to use distinct names) is of type `int[5][42]`, or "array 5 of array 42 of int". In the call, as in most contexts, it decays to `int (*)[42]`, or "pointer to array 42 of int". The problem is that the types "pointer to array N of int" and "pointer to array N of const int" are distinct and are not assignment-compatible. This seems to be a case where forbidding assignment does not promote safety. Assigning a `const int*` value to an `int*` object, if it were allowed, would permit bypassing const correctness, such as quietly permitting an attempt to assign a value to a const object. But prior to C23, the rules were a bit more strict than they need to be. A simple example: int main(void) { int (*x)[10]; const int (*y)[10]; x = y; // discards "const" y = x; } The first assignment is a constraint violation in all versions of standard C because it discards the "const" qualifier. The second gets the "before C23" diagnostic with gcc. (clang doesn't complain about it with either "-pedantic-errors -std=c17" or "-pedantic-errors -std=c23".) I'm actually not sure what specific changes were made in C23 in this area. I've compared the "Simple assignment" sections of C17 and C23 (drafts), and the only significant changes were to allow for values of type nullptr_t. -- Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com void Void(void) { Void(); } /* The recursive call of the void */