Path: utzoo!attcan!uunet!husc6!cs.utexas.edu!natinst!bigtex!james From: james@bigtex.uucp (James Van Artsdalen) Newsgroups: comp.sys.ibm.pc Subject: MS-C 5.0 var_args bug? Message-ID: <2664@bigtex.uucp> Date: 10 Jun 88 17:37:59 GMT Organization: F.B.N. Software, Austin TX Lines: 51 I am attempting to use the ANSI var_args support in MS-C 5.0, and have encountered what appears to be a bug in the stdarg.h header library. Has anyone else run across this? The problem is that Microsoft used sizeof() to determine the distance between objects on the stack, even though the stack size of objects is often not the same as it would be elsewhere. In particular, sizeof(char) is 1 (by definition), but while char occupies one byte in .data or .bss space, it occupies two bytes on the stack. Hence, if the fixed parameter in your function is a char, or any but the last variable argument is char, the Microsoft macros fail. This illustrates both problems. f(fixed) char fixed; { va_list ap; char c; va_start(ap, fixed); c = va_arg(ap, char); } Using the standard definitions below, #define va_start(ap,v) ap = (va_list)&v + sizeof(v) #define va_arg(ap,t) ((t*)(ap += sizeof(t)))[-1] the &v will generate the address of fixed, and sizeof(v) will add one, leaving ap set one byte too low: it points to the top half of the word that "fixed" is in, not to the first parameter. Similarly, in the va_arg() reference, ap is incremented by sizeof(t), or one, leaving ap pointing one byte too low again (ap should be left pointing at the next argument, if there is one). Presumably the problem occurs with structs too, but since I don't believe in passing structs as parameters, testing is left as an exercise to the reader. :-) My proposed solution is below. If any sizeof() is odd, it is incremented. I could have said ((sizeof(v) + 1) & ~1, but the code below is a little clearer to me at a glance. This looks bad, but it generates nearly optimal code, and works, which is what counts. #define va_start(ap,v) ap = ((va_list)&v) + (sizeof(v) + (sizeof(v) & 1)) #define va_arg(ap,t) ( *(t*)( (ap += (sizeof(t) + (sizeof(t) & 1))) - \ (sizeof(t) + (sizeof(t) & 1))) ) -- James R. Van Artsdalen ...!ut-sally!utastro!bigtex!james "Live Free or Die" Home: 512-346-2444 Work: 328-0282; 110 Wild Basin Rd. Ste #230, Austin TX 78746