[ACCEPTED]-Printf for struct? (C/C++, VC2008)-field

Accepted answer
Score: 10

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
Score: 5

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.

Score: 5

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.

Score: 4

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).

Score: 3

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);
Score: 2

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

Score: 2

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.

Score: 1

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