Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

char type in va_arg

Tags:

c

arguments

I have the following function which writes passed arguments to a binary file.

void writeFile(FILE *fp, const int numOfChars, ...)
{
   va_list ap;
   va_start(ap, numOfChars);
   for(int i = 0; i < numOfChars; i++)
   {
      const char c = va_arg(ap, char);
      putc(c, fp);
   }
   va_end(ap);
}

Upon compiling, I get the following warning from the compiler

 warning: second argument to 'va_arg' is of promotable type 'char'; this va_arg
      has undefined behavior because arguments will be promoted to 'int' [-    Wvarargs]

Now as I understand it, C wants to promote char type to int. Why does C want to do this? Second, is the best solution to cast the int back to a char?

like image 527
Aman Avatar asked Jan 20 '15 20:01

Aman


People also ask

What is Va_arg?

In the C Programming Language, the va_arg function fetches an argument in a variable argument list. The va_arg function updates ap so that the next call to the va_arg function fetches the next argument. You must call the va_start function to initialize ap before using the va_arg function.

Is Va_start is a macro?

The va_start macro enables access to the variable arguments following the named argument parm_n . va_start should be invoked with an instance to a valid va_list object ap before any calls to va_arg.

What does Va_arg return?

va_arg returns the value of the next argument in the list. The type is always the same as the second argument to va_arg . CAUTION. The results of va_start are unpredictable if the argument values are not appropriate. In certain cases, arguments are converted when they are passed to another type.

What is Va_list type?

va_list is a complete object type suitable for holding the information needed by the macros va_start, va_copy, va_arg, and va_end. If a va_list instance is created, passed to another function, and used via va_arg in that function, then any subsequent use in the calling function should be preceded by a call to va_end.

Why doesn't va_arg() accept char as the type argument?

But given the existence of prototypes, there's really no reason to write code that depends on such promotions -- except for the special case of variadic functions.) Because of that, there's no point in having va_arg () accept char as the type argument.

What does va_arg do in C?

The C library macro type va_arg (va_list ap, type) retrieves the next argument in the parameter list of the function with type. This does not determine whether the retrieved argument is the last argument passed to the function.

How to initialize an object in va_arg?

This object should be initialized by an initial call to va_start before the first call to va_arg. type − This is a type name. This type name is used as the type of the expression, this macro expands to.

What is a type name in va_arg?

A type name. This type name is used as the type of the expression this macro expands to (i.e., its return type). For a type expression to be suitable for its use with va_arg, it must be such that type* produces a pointer to type.


1 Answers

Now as I understand it, C wants to promote char type to int. Why does C want to do this?

Because that's what the standard says. If you pass an integral value with conversion rank smaller than that of int (e. g. char, bool or short) to a function taking a variable number of arguments, it will be converted to int. Presumably the reason for this has its roots in performance, where it was (and in fact, often it still is nowadays) better to pass values aligned to a machine word boundary.

Second, is the best solution to cast the int back to a char?

Yes, but you don't really need a cast even, an implicit conversion will do:

char ch = va_arg(ap, int);
like image 61
The Paramagnetic Croissant Avatar answered Sep 28 '22 12:09

The Paramagnetic Croissant