Jump to content

  • Log In with Google      Sign In   
  • Create Account


Compiler behaviour quiz


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
8 replies to this topic

#1 Adam_42   Crossbones+   -  Reputation: 2353

Like
0Likes
Like

Posted 26 January 2013 - 06:42 AM

Here's some example code:

 

#include <iostream>
 
using namespace std;
 
struct number { float x; };
 
number test_func(void) { static number v; return v; }
 
int main()
{
    const number one = { 1.0f };

    test_func() = one;
    test_func().x += 1.0f;
    
    cout << test_func().x << endl;
    
    return 0;
}

 

Mini quiz:

 

1. Without using a compiler look at the code. Would you expect any warnings or errors from the compiler? Why?

 

2. What would you expect the output to be if it compiled?

 

3. Now compare your results to what actually happens when you compile it. Is it what you expected?



Sponsor:

#2 Hodgman   Moderators   -  Reputation: 26985

Like
0Likes
Like

Posted 26 January 2013 - 06:52 AM

your static is returned as a copy...

[edit]A nice compiler might warn you that your assignments are to a temporary, and won't have any real effect in this case.

Edited by Hodgman, 26 January 2013 - 07:04 AM.


#3 Adam_42   Crossbones+   -  Reputation: 2353

Like
0Likes
Like

Posted 26 January 2013 - 06:54 AM

your static is returned as a copy...

 

I know. That's why the results are interesting. Try it on a few compilers ;)



#4 Rattenhirn   Crossbones+   -  Reputation: 1630

Like
0Likes
Like

Posted 26 January 2013 - 07:03 AM

If I haven't missed anything it should print "0" on all compilers.

Edit: And report no warnings or errors, except maybe about unused stuff.

Edited by Rattenhirn, 26 January 2013 - 07:05 AM.


#5 Adam_42   Crossbones+   -  Reputation: 2353

Like
1Likes
Like

Posted 26 January 2013 - 07:44 AM

Spoiler



#6 Rattenhirn   Crossbones+   -  Reputation: 1630

Like
0Likes
Like

Posted 26 January 2013 - 08:18 AM

Good to know that there's yet another instance where Clang points out non sensical code. I'm not sure it's correct though, but too lazy to check it... :)



#7 SiCrane   Moderators   -  Reputation: 9337

Like
4Likes
Like

Posted 26 January 2013 - 09:01 AM

Clang didn't even pick up the other line of code that is equally bad...

From the compiler's point of view it's not equally bad. For test_func().x += 1.0f, the compiler will see test_func() is an rvalue so test_func().x is also an rvalue, so if a primitive rvalue appears on the left side of an = then you've got a problem. However, for test_func() = one, it doesn't think of the = as a real =, it sees that the left hand side is a class type, so this is actually test_func().operator=(one). The . operator when the right hand side is a member function doesn't care if the left hand side is an rvalue, it only looks for the cv-qualifier such as const or non-const. In this case test_func() returns a non-const object so it can be bound to the compiler generated number & number::operator=(const number &) function.

#8 Servant of the Lord   Crossbones+   -  Reputation: 16685

Like
0Likes
Like

Posted 26 January 2013 - 09:24 AM

Apparently GCC catches it also. Here's my expected results before compiling and before reading others' comments:

1. Without using a compiler look at the code. Would you expect any warnings or errors from the compiler? Why?

"test_func() = one;"- Some kind of 'Assigning to r-value/temporary' warning, since test_func() isn't returning by reference.
 
Also, test_func(void) should be test_func(), no need for the 'void' there. I don't know if a warning will result. Probably something like "explicit void argument - compile with -ANSI to disable warning"
 

2. What would you expect the output to be if it compiled?

Undefined gibberish value - whatever 'static number v' initially resolves to, because it has never been assigned anything.
 

3. Now compare your results to what actually happens when you compile it. Is it what you expected?

Using GCC/MinGW 4.7.2:
 
I didn't get the warning I expected on assigning "test_func() = one;",
instead I got an *error* on on the member variable assignment version: "test_func().x += 1.0f;"
 
error: using temporary as lvalue [-fpermissive]
 
 
 
I only found out yesterday that this is valid and standardized C++:
const int &refToTemp = 357;
...it just only lasts to the end of the scope that the expression is contained in. Still it's useful for avoiding a copy in some circumstances, which is why I looked it up:
//Only makes a copy if 'condition' is false.
const std::string &myString = ( ...condition... ? this->memberString : this->GetCopyOfSubStr_ReturnByValue());
this->UseString(myString);

Edited by Servant of the Lord, 26 January 2013 - 09:31 AM.

It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.

[Fly with me on Twitter] [Google+] [My broken website]

All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.                                                                                                                                                       [Need free cloud storage? I personally like DropBox]

Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal


#9 SiCrane   Moderators   -  Reputation: 9337

Like
2Likes
Like

Posted 26 January 2013 - 10:45 AM

Also, test_func(void) should be test_func(), no need for the 'void' there.

(void) is a perfectly standard, legal alternative to () for function declarations that aren't destructors. It's not necessary, but neither is white space in most cases. Since (void) and () have a different meaning in C, giving a warning for this would annoy quite a few people who write or use headers that are meant to be used from both C and C++. And since that includes the C standard library headers, which every C++ compiler that is also a C compiler will have, this isn't a warning you'll find very often.

Undefined gibberish value - whatever 'static number v' initially resolves to, because it has never been assigned anything.

Objects with static storage duration, which includes function local static variables, are automatically zero-initialized before any other initialization takes place (if any). Since the class type lacks any implicit or explicit non-trivial constructors and the object has no other initialization, then zero initialization is the only thing that happens in this case.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS