I have a printf
-like function that can handle %s
(char *
) and %ls
(wchar_t *
) conversions. Everything works fine if I pass the right argument for the right conv specifier.
But if I pass a char *
to my function when it expects a wchar_t *
, it may segfault (Null-terminating byte being located at the second byte of a wchar_t
for instance). Since I access this argument through va_arg()
I can't be sure of the type.
If I consider that this char
array is always NUL-terminated, I could check byte after byte to correctly handle the NUL-terminating char and stop memory access after it. But then I wouldn't be able to handle wchar_t
legit values like this :
0b XXXXXXXX XXXXXXXX 00000000 XXXXXXXX
I'm already using the __attribute__
printf GNU C extension. But I this function may be used by a python programm through ctypes
, so format/type checking at compiling may not be enough.
It there a way to perform such checking at runtime in my C function?
(NB : "There is no such way" may be the answer, but I'm still asking in order to be completely sure.)
No, this is not possible.
In a typical C implementation, the type system only exists as an aid at compile time.* At runtime, all you have is bytes of data, and there's no way to even tell a pointer from a number (besides educated guessing).
Technically, you're not even allowed to va_arg(ap, const char*)
and then examine memory if the original argument was not a char*
, signed char*
, unsigned char*
or void*
, or a const
-related version of such a type. The type passed to va_arg
is always required to be a compatible type. (One reason is there's no guarantee pointers to different types have the same size, layout, and meaning.)
(*In C++ there's a bit more to the story, because data representing types is stored connected to polymorphic objects to make dynamic_cast
and typeid
work correctly, and associated with all exception objects to make catch
blocks work correctly. But none of this is compatible with va_arg
.)