This might be kind of a weird question, but I am a novice with __builtin_va_list and how it works.
I am creating a function with the following signature:
typedef signed char i8;
typedef long long signed int i64;
typedef long long unsigned int u64;
i64 f ( u64 arg_count , ... );
Ideally, the function is supposed to work like this under the hood:
i64 f ( u64 arg_count , u64* args );
I like that the ... syntax lets me take any number of arguments without explicitly defining an array first, but for the purposes of the function, I really want to explicitly cast each of the them all to u64 before parsing them in my function, and the __builtin_va_list does not allow me to do that without explicitly casting each argument .
For example, if I call:
i8 c = 27;
u64 i = 27;
f ( 2 , c , i );
and within the function pop an argument with __builtin_va_arg, I have to correctly predict the size of the incoming type in order to get the correct value. For example,
i64 f ( u64 arg_count , ... )
{
__builtin_va_list args;
__builtin_va_start ( args , arg_count );
u64 c = __builtin_va_arg ( args , u64 ); // This will be wrong because the first parameter was 8 bits, not 64
...
}
Explicit casting like this would work I suppose:
i8 c = 27;
u64 i = 27;
f ( 2 , ( u64 ) c , ( u64 ) i );
...but it is annoying to type for long lists.
Is there any way to accomplish the desired syntax using plain C / preprocessor? I usually just compile with Clang, but a fairly cross-platform solution would be ideal.
Instead of passing the values as arguments in a variable argument list, you can pass them as an array, using a compound literal:
(Additionally, I changed the code to use the standard type
uint64_t. There is no need to create user-defined types such asu64. It adds clutter and opportunity for confusion and bugs.)You can also have the macro count the arguments: