From: Maarten B. <sou...@ds...> - 2006-06-16 22:36:59
|
Felix, Anthony, The widening of the argument must take place exactly for functions like printf. Your solution is ok. The other solution is to always have the argument cast very explicitly when calling the function. char data ch= 0x15; SetVal(1, (char)(unsigned char)ch); A macro will probably come in handy in this case. Now you can use va_arg(ap, char) inside your function. Greetings, Maarten > Many thanks for this information; it is exactly what I observed: two > bytes get unstacked instead of one; without the twisting of MSB and > LSB this would have been ok. I consider the twisting of MSB and LSB to > be a bug. > > Anyway, I modified my SetVal as follows: > > void SetVal(unsigned char Type, ...) > { > va_list ap; > int n; > > va_start(ap, Type); > if (Type==1) { > n= va_arg(ap, int); > g_ch= (char)(n); > } > } > > This unstacks 2 bytes to an int (correct MSB/LSB order) and then casts > the int to the one byte char; now things are working. > > I just fear that one day somebody might remove the widening of the > arguments and then my workaround will fail. However this will never > happen since it would break all other (similar) code, including > printf. > > many thanks again for your help > > ------------------------- > > Felix > > Ant...@se... wrote: > > ANMscc> It is normal for variable args to be widened to type int. > ANMscc> Hence a char should be stacked as 2 bytes. It is correct > ANMscc> for the caller to stack 3 bytes. > > ANMscc> It may also be correct that the callee reads only 1 char > ANMscc> if you read the arguament into a char. The problem is that > ANMscc> it read the MS byte instead of the LS byte, perhaps the > ANMscc> code generator forgot that it's reading from an int as it's > ANMscc> varargs. > > ANMscc> In a typical implementation of printf, a %d would cause it to > ANMscc> unstack an int, whether you gave it a char or an int, it doesn't > ANMscc> care. Since the caller widens to int, it doesn't need to know. > ANMscc> %c might cause it to try to read into a char. Actual coding of > ANMscc> printf I've seen re-use variables and read the arg of %c into > ANMscc> an int. A bug like this may not break printf, and a working > ANMscc> printf is not a sufficient test of varargs. > > ANMscc> Widening args was very common in the K&R days but has > ANMscc> all been forgotten now we have ansi prototypes. Except > ANMscc> in varargs, where it still lurks to catch you out. Getting rid > ANMscc> of widening completely would break printf. > > ANMscc> Ant |