Authors: Jay Ghiron
Date: 2026-06-24
Submitted against: C23
Status: Open
Considering the following program:
#include<stddef.h>
char(**foo(size_t x))[]{
static char(*p)[x];
return&p;
}
int main(){
char(**a)[1]=foo(1);
*a;/* lengths match, valid */
char(**b)[2]=foo(2);
*b;/* ? */
*a;/* ? */
}
The first time the declaration of p is reached, x has value one so
it creates a pointer to an array of one char. The first *a should
therefore be valid, since the length expressions have the same value.
The second time the declaration of p is reached, x has a value two
which is different than the previous time the declaration of p was
reached. The result of that is unclear, the following are some
possible results:
foo(2).*b is undefined
and the second *a is valid.*b is valid and the
second *a is undefined.*b is valid and the second *a is valid.The first interpretation could be justified by:
All declarations that refer to the same object or function shall have compatible type; otherwise, the behavior is undefined.
(C23 6.2.7 "Compatible type and composite type" paragraph 2.)
Though this text was present in initial standardization before
variable length arrays existed, and presumably is intended to apply to
identifiers with linkage rather than this scenario. It would also
make being able to use variably modified types with static storage
duration or thread storage duration almost entirely useless. What is
the intended result of this program? This is also observable with
automatic storage duration when using goto:
int main(){
char(**c)[1],(**d)[2];
l:;
char(*q)[++(static int){}];
if(sizeof(*q)==1){
c=&q;
*c;/* lengths match, valid */
goto l;
}else{
d=&q;
*d;/* ? */
*c;/* ? */
}
}
Note that the object must have variably modified but not variable length array type for this scenario, an object with variable length array type does not exist for the entire block that contains it.