Authors: Jay Ghiron
Date: 2026-06-16
Submitted against: C23
Status: Open
Cross-references: 0032
An implementation may accept other forms of constant expressions, called extended constant expressions. It is implementation-defined whether extended constant expressions are usable in the same manner as the constant expressions defined in this document, including whether or not extended integer constant expressions are considered to be integer constant expressions.
(C23 6.6 "Constant expressions" paragraph 14.)
This wording does not clearly define limitations on what the
implementation can consider extended integer constant expressions
(beyond the implied requirement that it has to always evaluate to one
value). DR 32 was resolved as comma operators not being
allowed, though the response "The intent of the statement ... is to
allow an implementation to accept syntactic forms, such as might be
generated by the offsetof macro, that may not otherwise be
semantically allowed." does not seem entirely accurate now
considering:
int arr_or_vla[(int)+1.0];
This is explicitly mentioned as an example of when extended integer constant expressions can change the semantics, despite not being of a syntactic form outside of the standard. Was it intended for there to be any limitations on what can be considered an extended integer constant expression? Consider:
#include<errno.h>
void other();
int main(){
char(*p)[errno+1];
return sizeof*(other(),p);
}
Suppose the implementation knows that main is never named in other
translation units, therefore main can never be reentered. Would it
be valid therefore to treat errno+1 as an integer constant
expression since it has a definite result of one? Moreover, even if
other did set errno to one and reenter main could treating
errno+1 as an integer constant expression be justified by the fact
that by doing so it removes the possibility of main being reentered?
Also, consider:
#include<stdio.h>
int main(int n,char**){
char(*q)[n?n:1];
sizeof*(puts("is executed"),q);
}
If the implementation could somehow guarantee an exact value of n,
could it therefore treat n?n:1 as an integer constant expression and
skip printing "is executed"? Another location where this is visible
is the formation of null pointer constants:
#include<errno.h>
int main(){
int*r=errno;
}
Can an implementation accept errno here as a null pointer constant?