[ACCEPTED]-Printf for struct? (C/C++, VC2008)-field
If you want a cast, then cast it:
struct A
{
int a;
int b;
int c;
operator int()
{
return a + b + c;
}
};
A a = { 10, 20, 30 };
printf("%d\n", (int)a);
the output 1 will be
60
It's undefined behavior, so in a certain 13 sense every possible behavior can be termed 12 "normal" for this function call. It can 11 be explained though.
printf
takes a variable number 10 of arguments after the format string. How 9 these are packed is left to the implementation. It 8 seems that Visual C++ packs the arguments 7 in memory the same way it packs the members 6 of your struct A
, so every time it calls va_arg
internally, it 5 gets the next element in a
.
As regards the 4 casting, you can't rely on autocasting in 3 a varargs context, since the optional parameters 2 have no type. printf
is declared as int printf(char const *, ...)
. ...
is a range 1 of untyped parameters.
There is no such thing like C/C++, your 11 code is just a mixture of the two. In particular 10 it doesn't compile with a standard C compiler 9 because you are missing the struct
keyword in 8 the declaration of a
.
For your use of printf
. First 7 of all you shouldn't if this is C++. It 6 has its own mechanisms for IO. Use them.
Then 5 placing a structure as an argument in a 4 ...
list is undefined behavior. You just had 3 bad luck, and the compiler did what it did. It 2 could just have sad "no, no, don't do that", or 1 at least have given you a warning.
You placed three integers on the stack, and 4 then retrieved three integers (one per "%d"). Yes, it 3 is normal - but in the realm of "really 2 ugly hack" (and Undefined Behaviour to boot, as 1 plinth correctly commented).
This works by accident. Most times when 3 your printf
arg count or types do not match the 2 results will not be pretty.
If you want C++ use 1 ostream/cout
std::cout << a.a << ' ' << a.b << ' ' << a.c << std::endl;
If you want non-brittle C code use:
printf("%d %d %d\n", a.a, a.b, a.c);
it's because of memory layout of the struct. the 4 ints are straight after each other. so putting 3 the struct in the printf call is basically 2 putiing the same as putting each one on 1 one after the other
There's a lot of compiler/environment dependent 15 stuff in how printf might behave.
printf 14 ostensibly uses C's var args features where 13 when you have a declaration
int printf(char* formatStr, ...)
you can pass 12 multiple arguments in the "...". Then in 11 the body of printf you would do something 10 like the following
// count how many formatters are in the format string
// and calculate "amount"
// here amount = 3
va_list valsToPrint;
va_start(valsToPrint,amount);
for (int i = 0; i < amount; ++i)
{
// treat each value as a 32-bit int and print it
}
va_end(vl);
The important thing is 9 -- there's a lot of compiler/environment 8 dependent stuff in here. Such as the fact 7 that the struct is probably packed so that 6 each value shows up on 32-bit boundaries 5 and how the va_list is actually determined 4 from the compiler. I imagine compiler-to-compiler 3 there could be some very different behavior 2 from your code, but its not entirely surprising 1 that exhibits the behavior you describe.
printf() has "(char *, ...)" signature. That 11 means it is up to "printf" function to handle 10 all arguments after "char *".
You pass a 9 struct A to printf(). In memory it has following 8 layout: "int, int, int". printf() function 7 reads format string ("%d %d %d") and "thinks" that 6 you passed 3 integers to it. And this "assumption" coincides 5 with the struct's layout. So it prints all 4 its fields as separate values.
Try to remove 3 "b" field and you will see that printf() will 2 print values of "a" field, "c" field and 1 SEGMENTATION FAULT.
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.