https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14557
felix <felix.von.s at posteo dot de> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |felix.von.s at posteo dot de --- Comment #19 from felix <felix.von.s at posteo dot de> --- The number of duplicates of this report isn't terribly high, but doesn't this at least deserve a mention in the 'Disappointments' section of the manual? In any case, the following macro could be used as a workaround, under some rather reasonable assumptions: #if __STDC_VERSION__ >= 201112L #define va_ptr(ap) _Generic(&(ap), va_list *: &(ap), default: (va_list *)(ap)) #elif __GNUC__ >= 4 #define va_ptr(ap) __builtin_choose_expr(__builtin_types_compatible_p(__typeof__(&(ap)), va_list *), &(ap), (va_list *)(ap)) #else #define va_ptr(ap) (sizeof(ap) == sizeof(va_list) ? (va_list *)&(ap) : (va_list *)(ap)) #endif The main assumption is that a pointer to an array is the same as a pointer to its zeroth element, i.e. when we have a variable T array[N]; then (&array == (T (*)[N])array); or at least that this holds for the array type that va_list is. I don't see anything in the C standard that would explicitly guarantee this, but this should be a safe assumption to make, because breaking it would presumably make the following memcpy calls non-equivalent: T array0[N], array1[N]; memcpy(array1, array0, sizeof(array0)); memcpy(&array1, array0, sizeof(array0)); memcpy(array1, &array0, sizeof(array0)); memcpy(&array1, &array0, sizeof(array0)); which would be strange. Furthermore, the last version will break in the presence of va_list defined like typedef void *va_list[1]; typedef char va_list[sizeof(char *)]; but I think it's reasonable to assume that no ABI standard is going to prescribe something like this. None of the targets currently supported by GCC do.