Abusing C++

Time for a quiz.

What does this code print out?

int tmp[3];
tmp[0] = 314.15;
tmp[1] = 3.1415;
int *P = tmp + 1;

printf("The result is: %f\n",
       tmp[0]/*P              /* the tricky bit */
      );

Brave souls may post an answer below, but hold off on explaining your thinking for now.

I’ll say an answer of 314, but there are many things in there that are weird, which I guess I’ll hold off on explaining why it’s confusing?
Would it be ok to reply using a “hide details” thing?

Like this example hidden text? (drop down the triangle to view hidden text)

You are now viewing the spoiler/hidden text

I don’t anybody to give it away just yet.
I’ll give an answer on Monday evening, but I won’t explain why, so after that we’ll let the theories run wild.

Well the turnout was a bit disappointing, but the answer is in fact:

314

Now the question is: why?

It’s ALL tricky parts. that was mean! :slight_smile:

  1. The elements of the array tmp[] are assigned floats, but the type is int, so only whole numbers result.
tmp[0] = 314
tmp[1] = 3
  1. Difficult to know things:
    The asterisk placement for a pointer is shown immediately after char or int in the lesson, but before the variable in the quiz. so…that is a bit confusing as it doesn’t matter apparently.
    Also, just plain tmp is the same as &tmp[0], meaning “whatever is in the first element of the array”. How would one know that?
    So doing int *P = tmp + 1; means a pointer of type int named P points to the memory address of tmp[0] plus 1 element forward, which is tmp[1], which holds the value 3.

  2. It looks like we’ll print what’s in tmp[0] (which is why I ventured to just say 314), BUT…
    while the “%f \n” inside quotation marks seems like it might just print as-is, like “The result is %f \n 314”, there are a couple of things about the printf line that are not as they seem.
    First, %f is actually a format specifier for float and wouldn’t print as-is as just “%f”. Instead it would attempt to print the answer as a float. But tmp[0] is an int, so wouldn’t this be a type mismatch and cause an issue?
    Then, the “\n” means “do a line return here”, so the answer would be on the next line.

  3. Lastly, the /*P looks like it should be a division operation using tmp[0] and the P pointer somehow, but it’s actually an opening of a comment block.
    The /* in “/* the tricky bit” is ignored, and the comment finally actually closes at */
    In other words, this whole thing is a comment /*P /* the tricky bit */

So printing tmp[0] might show up as 314? Or it’s going to explode because of the type mismatch, I don’t know.

This is a very good point, and one that I missed when I wrote this.
The result will depend on how smart the compiler is.
A stupid compiler will just compile this and push an integer on the stack and then try to print it like a float, which will probably result in a very very small number, something like 1.3e-52 or something…

A smart compiler will realize that the %f and the int doesn’t match, and print an error message.

printf is a special function, because the argument types depends on the string, and that’s not normally how things work, so any type inference is compiler specific and not stricly a part of C/C++.

So the moral of the quiz was mostly int vs float, and the comment part then?
Could you expound on the placement of the pointer asterisk?
How is it generally done in ProffieOS?

The pointer asterisk is meant to show why /* was not a great choice for "begin a comment. The solution is to put spaces around your operators.

   a=10/*p;   // this is bad
   a = 10 / *p; // this is fine

In ProffieOS we more or less follow the google rules for how to format the code, which requires spaces around operators.

I think the moral of the story is that C++ is hard sometimes.
I tried writing another “abusing C++” post yesterday, but this time I actually compiled and tested the program, and I didn’t get the result I expected. I’m reasonably good at C++, but the results were still not what I expected. This sort of thing rarely happens in other programming languages. C++ is special.

2 Likes

My machine (trying multiple different variations) consistently produced 0. It being undefined behavior and hardware/compiler differences probably have to do with it.

To be completely fair, I don’t know what you were trying to do in that other example, but in this particular one, I would hardly call it a C++ question. C variadic functions (which is what printf is and where the problem happens if any) have always been ugly and less than ideal for most things because of stuff like that, and everything here is pure C.

A C++ variadic function would probably be much more deterministic and produce expected results (or an expected compiler error/warning).

EDIT: Btw, this is why I like list initialization… it greatly reduces initialization ambiguity for things like this. Even though this particular truncation should be pretty easy to spot for anyone with a little bit of experience. (And in fact virtually all static analyzers/linters will point it out too)

Without plugging it in, it looks like you wanted it to keep going reading out the integers infinitely? That’s a lot of pi(e) to digest, especially for a program. Like it got “so full of pie it had to stop". :grin:

Also damn you, now I want apple pie.

1 Like

The value for tmp[0] will be 314, but what printf outputs will be based on the compiler. GCC 11 will give:
The result is: 0.000000

3 Likes