ID Number: Q71772
5.10 6.00 6.00a | 5.10 6.00 6.00a
MS-DOS | OS/2
Summary:
Variable arguments of type char are not the size expected by the
macros va_start and va_arg. If a procedure with variable parameters
uses either va_start or va_arg on a char variable, all subsequent
parameters retrieved with va_arg will return an incorrect value.
Although the use of char size values with the macros for variable
argument functions usually causes unexpected results, this behavior is
compatible with the ANSI specification.
The functionality of the "va" macros has been modified in Microsoft C
version 7.0 so that arguments of type char will handled as intended,
rather than giving unexpected results.
More Information:
All variables of type char are pushed onto the stack in 2 bytes,
rather than 1 byte. Both va_start and va_arg use a sizeof operation to
decide how much to move the frame reference. Because sizeof returns a
value of 1 for a char type, even though a char is actually stored in 2
bytes on the stack, va_start initializes the frame reference
incorrectly and va_arg increments the frame reference incorrectly.
In the sample code below, four characters are passed to a function
that takes variable arguments. The function should print all four
characters in order, but this is not the case, as demonstrated by the
sample output below. Because the frame reference is off, the first
character prints, then there is a blank space, then the second
character prints, and finally there is another blank space. Either of
the following workarounds can be used to adjust the frame reference
and get the desired results:
1. Change each occurrence of char to int. If necessary, typecast the
result to type char.
-or-
2. Change char to int in the call to va_arg. This requires an
additional new macro to use in place of va_start (when the last
declared parameter is of type char). For example:
#define va_start_char(ap,v) (ap) = ((va_list) (&v) + sizeof(int))
Sample Code
-----------
#include <stdio.h>
#include <stdarg.h>
void my_print( int num, char first, ... );
void main()
{
printf( "\nCharacters passed: a b c d" );
printf( "\nCharacters printed: " );
my_print( 4, 'a', 'b', 'c', 'd' );
}
void my_print( int num, char first, ... )
{
int count;
char temp = first;
va_list marker;
va_start( marker, first );
for( count=1; count<num; count++ )
{
printf( "%c ", temp );
temp = va_arg( marker, char );
}
printf( "%c\n", temp );
va_end( marker );
}
Program Output
--------------
Characters passed: a b c d
Characters printed: a b