offsetof and va_arg handling of commas outside of parenthesesAuthors: Jay Ghiron
Date: 2026-06-26
Submitted against: C23
Status: Open
offsetof contains wording to forbid the following:
#include<stddef.h>
int main(){
offsetof(struct{int x,y;},y);
}
offsetof(type,member-designator)which expands to an integer constant expression that has type
size_t, the value of which is the offset in bytes, to the subobject (designated by member-designator), from the beginning of any object of type type. The type and member designator shall be such that given
statictypet;then the expression
&(t.member-designator)evaluates to an address constant. If the specified type name contains a comma not between matching parentheses or if the specified member is a bit-field, the behavior is undefined.
(C23 7.21 "Common definitions <stddef.h>" paragraph 4.)
However, there does not appear to be any equivalent wording for
va_arg:
#include<stdarg.h>
void f(...){
va_list v;
va_start(v);
va_arg(v,struct{int a,b;});/* OK? */
va_arg(v,char(*)[0?1,2:3]);/* OK? */
va_arg(v,char(*)[(constexpr int){1,}]);/* OK? */
va_arg(v,int[[,]]);/* OK? */
va_end(v);
}
And offsetof does not have wording to forbid commas outside of
parentheses in the member-designator:
#include<stddef.h>
int main(){
struct S{int z[4];};
offsetof(struct S,z[0?1,2:3]);/* OK? */
offsetof(struct S,z[(constexpr int){1,}]);/* OK? */
}
Existing implementations reject both of these uses just like commas
outside of parentheses in the type of offsetof. I assume the intent
is to not allow these uses. A correction should consider that macros
can expand to include commas outside of parentheses as well:
#include<stdarg.h>
#define T int[[,]]
void g(...){
va_list w;
va_start(w);
va_arg(w,T);
va_end(w);
}
This would break with a definition of va_arg such as:
#define __va_arg(list,type)/*...*/
#define va_arg(list,type)__va_arg(list,type)
Since T will already be expanded by the time __va_arg begins
expansion. It may also be useful to add wording that clearly forbids
expressions from containing commas outside of parentheses, for any
standard library macro (other than assert). This has always been
implied, but does not actually appear to be stated.