YoYoYonnY YoYoYonnY - 2 months ago 15
C Question

Obtaining C varargs with char[]

I am writing a container library in

C
, and I would like to use varargs in my implementation, like so:

void stack_push(stack *self, T item);
T stack_pop(stack *self);


Obviously, C does not have generic types, so instead I use
void *
pointers:

void stack_push(stack *self, void *item);
void *stack_pop(stack *self);


However, I am thinking of passing input using varargs:

void stack_push(stack *self, ...);


This could work, because item size is determined at container initialization.

My question is: Is it valid
C
to access vararg members using different type with the same size?

void stack_push(stack *self, ...)
{
struct wrapper {
char item[self->item_size];
};

va_list ap;
struct wrapper item;

va_start(ap, self);
item = va_arg(ap, struct wrapper);
va_end(ap);

stack_grow(self, self->size+1);
memcpy(self->items+self->item_size*self->size++, &item, self->item_size);
}

alk alk
Answer

Doing as you intend provokes undefined behaviour.

From the C-Standard (C11 draft):

7.16.1.1 The va_arg macro

Synopsis

1

#include <stdarg.h>
type va_arg(va_list ap, type);

Description

2 [...] if type is not compatible with the type of the actual next argument (as promoted according to the default argument promotions), the behavior is undefined, except for the following cases:

— one type is a signed integer type, the other type is the corresponding unsigned integer type, and the value is representable in both types;

— one type is pointer to void and the other is a pointer to a character type.

None of the two exceptions seem to match your use-case.

Comments