J
jononanon
Hi there!
Check this out -> the following code always works:
printf("%d %d %d", (char)'\1', (short)2, 3);
// prints: 1 2 3
So a conversion specifier of %d works with type int, or "SMALLER" integer-types (short or char) !!!
Why does this work??
Is my explanation correct?
->
With printf("%d", (char) '\1')
the argument 1 lands on the stack not as char parameter, but as a parameterpromoted to int, and the library code that handles the access to the parameter uses va_arg(ap, int) to access it. You can never use va_arg(ap, char) -> that would distroy a consistent handling of the stack-parameters!
When handling parameters on the stack, the size from one parameter to the next is never smaller than an int. (Even when NOT using variable arguments. Right? -> ref in C-std??)
Is this called argument promotion?
Demo:
/*
demonstration that char on stack nonetheless occupies the space of an int!
Not only does it occupy the space of an int, but all bytes comprising that int are set correctly! not just the single byte corresponding the the char.
(How does one call this: argument promotion????
Or is this part of integer promotion of a literal????)
*/
int func(char a, char b, char c)
{
const char *p = &a;
printf("a=%d\n"
"b=%d\n"
"c=%d\n", p[0],
p[-(int)sizeof(int)],
p[-(int)sizeof(int) * 2]);
/* don't do this. might probably work on x86 with gcc (but again: don't do this)
If you want to do something like this portable, please use stdarg.h instead!
*/
}
Now, since printf("%d", arg) with its variable argument list, is implemented in the C library with stdarg.h's va_arg(ap, type)
and type may not be a "smaller" type than int, it so happens that the particular code for handling the conversion specifier "%d" uses va_arg(ap, int).
And that's the explanation!
Is it correct?
Can someone point out relevant parts of the C11 standard, that show that this handling of parameters in the stack must never occupy space of less thansizeof(int)??
And: ahhh... is this a issue of handling the stack; OR part of integer promotion of char-literals?? Two separate issues, or one and the same??
Examples with questions:
1)
printf("%d", '\1');
Here '\1' is promoted to int (integer promotion) and then put on the stack as integer?
2)
printf("%d", (char)'\1');
Does normal integer promotion of the literal char occur here? I think no.
Here a different type of promotion occurs, which is the one of handling theparameter stack??
I realize that I'm a bit confused, and may have things half-correct or so....?
Can someone give a good explanation.
Thanks so much!!
J.
Check this out -> the following code always works:
printf("%d %d %d", (char)'\1', (short)2, 3);
// prints: 1 2 3
So a conversion specifier of %d works with type int, or "SMALLER" integer-types (short or char) !!!
Why does this work??
Is my explanation correct?
->
With printf("%d", (char) '\1')
the argument 1 lands on the stack not as char parameter, but as a parameterpromoted to int, and the library code that handles the access to the parameter uses va_arg(ap, int) to access it. You can never use va_arg(ap, char) -> that would distroy a consistent handling of the stack-parameters!
When handling parameters on the stack, the size from one parameter to the next is never smaller than an int. (Even when NOT using variable arguments. Right? -> ref in C-std??)
Is this called argument promotion?
Demo:
/*
demonstration that char on stack nonetheless occupies the space of an int!
Not only does it occupy the space of an int, but all bytes comprising that int are set correctly! not just the single byte corresponding the the char.
(How does one call this: argument promotion????
Or is this part of integer promotion of a literal????)
*/
int func(char a, char b, char c)
{
const char *p = &a;
printf("a=%d\n"
"b=%d\n"
"c=%d\n", p[0],
p[-(int)sizeof(int)],
p[-(int)sizeof(int) * 2]);
/* don't do this. might probably work on x86 with gcc (but again: don't do this)
If you want to do something like this portable, please use stdarg.h instead!
*/
}
Now, since printf("%d", arg) with its variable argument list, is implemented in the C library with stdarg.h's va_arg(ap, type)
and type may not be a "smaller" type than int, it so happens that the particular code for handling the conversion specifier "%d" uses va_arg(ap, int).
And that's the explanation!
Is it correct?
Can someone point out relevant parts of the C11 standard, that show that this handling of parameters in the stack must never occupy space of less thansizeof(int)??
And: ahhh... is this a issue of handling the stack; OR part of integer promotion of char-literals?? Two separate issues, or one and the same??
Examples with questions:
1)
printf("%d", '\1');
Here '\1' is promoted to int (integer promotion) and then put on the stack as integer?
2)
printf("%d", (char)'\1');
Does normal integer promotion of the literal char occur here? I think no.
Here a different type of promotion occurs, which is the one of handling theparameter stack??
I realize that I'm a bit confused, and may have things half-correct or so....?
Can someone give a good explanation.
Thanks so much!!
J.