Variable Argument Macros Do Not Expect Arguments of Type char

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