Argument Evaluation Order in C++
Key Takeaways
Explains argument evaluation order in C++, covering syntax and standards
Full Transcript
hey so guys my name is Jonah welcome back to my sea loss loss series so today I wanted to talk about something a little bit different in fact I want to start kind of like a mini series within this C++ series just talking about random C++ things like tips and tricks that kind of stuff that will hopefully help you guys with some of the more intricate maybe less known features of C++ or just traps along the way because Sabo's was is full traps this basically just started off with me having a long list of things that are just weird and things that I thought that I should probably mention at some point in this series but didn't really have either the time or the necessity or July just didn't know where to fit them in because that they're just kind of you know little small things and this by the way this is just a prop the list is on Charlie but the point is there is much to discuss about C++ and so this is where this series comes in so I hope you guys enjoy it today I wanted to talk about something called argument evaluation order so in other words if I write a function that has a bunch of arguments and I pass a bunch of arguments into that function what order do the arguments get evaluated in because amongst the arguments I can actually write expressions which evaluate those arguments I don't have to pass in the number five into a function that takes in an int I can pass X plus y or five plus eight so if I do that and if I have a lot of arguments does the first argument get done first and then the second argument gets evaluated and the third one does it go in reverse order what happens how does this work and the interesting thing is that most people don't know most people don't know what this order of evaluation actually is what do you think it is pause this video right now and drop a comment below with your answer it'll be really interesting to see what the general community thinks and don't look it up anyway pretend this is like a job interview or something like that and the thing is if you're wrong or if you don't know the answer I don't blame you because this is not something that really comes up in programming it almost sounds like something that should actually come up more often than it does but when you're actually writing C++ code you don't really think about this and I think it's perfectly reasonable to not know the answer to this because it is kind of it does involve knowing a little bit more about how the compiler to compile occurred what the C++ standard actually specifies for C++ compilers and also just a lot of experience I think will probably lead you to I guess naturally knowing the answer to this and we're gonna dive in here and take a look at some examples and just explore this general problem but first I want to give a huge thank you to Skillshare for sponsoring this video for those of you who don't know Skillshare is an amazing online learning community where millions come together to take the next step in their creative journey it's a massive platform filled with thousands of inspiring classes for people who want to learn a new skill they've got so many amazing classes on there I particularly like a lot of their illustration classes for example this one is pretty cool they've even got stuff about productivity in general so how to improve your productivity because who does not like being productive and who does not struggle with that and a $10 per month for an annual subscription it has great value and a great way to spend your time learning new skills Skillshare is offering two months of free Skillshare premium membership to the first thousand people who sign up using the link in the description below so make sure you guys check that out for free and learn something new today speaking of learning something new let's take a look at this argument evaluation order shall we okay so here I have a super simple function called print sum that just takes in two integers and adds them together prints the result as well as the two integers that we're feeding into it is just a really simple example which will help illustrate this in action so let's go ahead and create a value here let's set it to zero and then I'm going to call print sum now what I'm going to do is write an expression here that needs to get evaluated at some point so I'm not just going to pass in value I'm gonna pass in value plus plus and I will do this twice so this is a really simple example to illustrate exactly what I'm talking about what will be printed and if you still haven't left a comment please leave one right now I'm really interested to see what you guys think and I'll be honest going through this code I would probably expect it to be something like maybe 0-4 like this one and then one for this one if it's evaluating them in reverse order maybe will in fact be zero and one obviously this is a post increment operator meaning that the original value should get passed in first then incremented but then again that's just my guess so I expect a to be either 1 or 0 and then B to be either well 0 or 1 depending on what a was this is probably what I would guess but then again I would be wrong because the answer to this is it's undefined behavior the C++ standard does not actually define what should happen in the situation which means it's undefined behavior means that it's going to vary compiler to compiler is completely dependent on the actual implementation of the sample source compiler that has to then translate this code into machine code basically that means this is unreliable and it will be different so why don't we do some testing let's go ahead and run this code right now and see what we get ok so this is my output 1 plus 0 equals 1 ok interesting so it looks like it passed in 0 for this first value and then 1 so I guess I was right when I said 1 plus 0 equals 1 I'm using the microsoft visual studio compiler here MSB C and I'm running in debug mode let's try release mode and see what we get hang on a minute and see your plus 0 equals 0 what so this doesn't work at all in release mode why does this differ release mode to debug mode what if I change this post increment to be a kind of pre increments on other words it should increment the value variable first and then pass it into the function let's switch both of these to be like this so in other words now if it follows that kind of this parameter is evaluated first in this parameter order we should get 1 and 2 I guess let's run this code I'm in release mode now and I get 2 plus 3 equals 4 so the value is just true for both of these what about running it in debug mode I also get to boss two equals 4 so this seems kind of I guess at least deterministic between debug and release mode but overall the point of this exercise is so that you can see that this is a complete mess because it's undefined behavior you can't predict this behavior it you're not supposed to do this now the case that is particularly interesting to me is this kind of release mode case of the post increment operator so in other words 0 plus 0 equals 0 what is even happening here the reason this is happening is the the compiler is actually allowed to work out what these are in parallel it does not have to first evaluate these arguments in a specified order to see what they are know when trying to kind of figure out what this isn't using like constant folding in release mode and various other optimizations that basically allow you to work out the value of variables in compiled time so in other words if I wrote two plus five instead of actually doing two plus five on the CPU at runtime it would just set value to seven because that would be a lot simpler and it's definitely something that can be calculated your in compile time the point being that it does not have to first do this in some kind of order where we have value plus plus and then that's one and therefore since has been changed to one it now uses that one to increment here which means that one gets passed into here and then increment it to two it doesn't need to do that it's actually able to kind of just be like okay well value zero value plus ply okay so zero pass and zero here busting zero here then do a little plus plus at the end it doesn't really matter it's allowed to do that up until C++ 17 so the interesting thing is if we change this to actually use the C++ 17 standard instead of like 14 or lower then if I run this we're actually going to get a different result and in fact we're going to get 1 plus 0 equals 1 because the C++ standard added a new rule starting with C++ 17 that postfix expressions have to be evaluated before each other expression and with respect to that of any other parameter meaning they have to be done one after the other it still doesn't really it's still it's still not deterministic which order it will actually be evaluated in meaning will this be 1 and this be 0 or is it gonna do 0 and then one for the a and B variable respectively this water is still undefined however they're now not going to be the same because it has to do one after the other let's explore this in different compilers so to summarize it looks like in C++ 17 which is probably what you're using anyway at least C++ 17 maybe you're even one of the cool kids using the C++ 20 draft one plus zero equals one is what we get using visual Studios compiler now I like using a little website here called one box.org it's basically just a little online compiler which has a whole bunch of difference here both lost as well as different compilers as you can see if I paste our code into there and run it using GCC and the C++ 20 draft and first of all you'll notice this is a little bit more helpful than the MSB C compiler which gave us no warnings this at least tells us that this operational value may be undefined which you know is correct but you can see we also get one plus zero equals one now going back to your like CL plus 14 let's see what that gets us still 1 plus 0 equals 1 interesting and then finally let's switch over to clang and take a look at what clang gives us and I'll run this in civil floss 20 here 0 plus 1 equals 1 interesting so it looks like clang does it the other way around and then finally if I drop back to sea levels 14 just just to see I also get 0 plus 1 equals 1 but you can see the clang also does in fact warn us so it's just m/s VC who seems to just I'm not even sure why they don't at least print a warning for something like this but you can see if I rebuild this in either debug mode or release mode it's not gonna warn me at all about anything wrong with my code so thanks I'm Susie so to summarize if you get this question in a job interview or programming test or whatever the correct answer is it's undefined because C++ does not actually provide the superevil specification does not actually provide a definition for what should happen in the situation of what order parameters or arguments should get evaluated in but bonus points if you mentioned that Sables law 17 does say that these things cannot be done at the same time that is to say that they have to be done one after the other but again the order is not actually defined in the specification which means that you technically have no way of knowing what this is leave your thoughts in the comment section below in case I missed something or I didn't test it in some kind of mode that you that you have tested it in then drop a comment below let's share some knowledge in this community because we're all in this together I hope you guys enjoyed this new kind of mini suppose loss series style video let me know other topics that you want me to cover in the future and finally don't forget the Skillshare is offering the first 1,000 people who click the link in the description below to three months of Skillshare premium I will see you guys next time goodbye [Music]
Original Description
The first 1000 people who click the link in the description will get 2 free months of Skillshare Premium: https://skl.sh/thechernoproject7
Patreon ► https://patreon.com/thecherno
Instagram ► https://instagram.com/thecherno
C++ standard source ► http://eel.is/c++draft/expr.call#8
Twitter ► https://twitter.com/thecherno
Discord ► https://thecherno.com/discord
Series Playlist ► https://thecherno.com/cpp
Watch on YouTube ↗
(saves to browser)
Sign in to unlock AI tutor explanation · ⚡30
Playlist
Uploads from The Cherno · The Cherno · 0 of 60
← Previous
Next →
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
3D Game Programming - Episode 1 - Window
The Cherno
3D Game Programming - Episode 2 - Game Loop
The Cherno
3D Game Programming - Episode 3 - Arrays
The Cherno
3D Game Programming - Episode 4 - Drawing Pixels!
The Cherno
3D Game Programming - Episode 4.5 - How Rendering Works
The Cherno
3D Game Programming - Episode 5 - Playing with Pixels!
The Cherno
3D Game Programming - Episode 6 - Performance Boosting
The Cherno
3D Game Programming - Episode 7 - FPS Counter
The Cherno
3D Game Programming - Episode 8 - Alpha Support and More
The Cherno
3D Game Programming - Episode 9 - Beginning 3D
The Cherno
3D Game Programming - Episode 10 - Floors and Animation
The Cherno
3D Game Programming - Episode 11 - Rotation
The Cherno
3D Game Programming - Episode 12 - User Input
The Cherno
3D Game Programming - Episode 13 - Render Distance Limiter!
The Cherno
3D Game Programming - Episode 14 - Basic Mouse Movement
The Cherno
3D Game Programming - Episode 15 - Textures + More!
The Cherno
3D Game Programming - Episode 16 - Walking, Crouching, Sprinting + More
The Cherno
3D Game Programming - Episode 16.5 - Exporting Runnable Jars
The Cherno
3D Game Programming - Episode 17 - Small Adjustments + Birthday!
The Cherno
3D Game Programming - Episode 17.5 - Creating an Applet
The Cherno
3D Game Programming - Episode 18 - The Beginning of Walls
The Cherno
3D Game Programming - Episode 18.1 - A Few More Things
The Cherno
Episode 18.5 - Creating an EXE File in Java
The Cherno
3D Game Programming - Episode 19 - Rendering Walls
The Cherno
3D Game Programming - Episode 20 - Continuing Walls, Fixing Bugs, and Managing Crashes
The Cherno
3D Game Programming - Episode 21 - Texturing Walls, Fixing Clipping, and Fixing the Mouse
The Cherno
3D Game Programming - Episode 22 - Random Level Generator + Properly Fixing Clipping
The Cherno
3D Game Programming - Episode 23 - Graphical User Interface (GUI) Launcher
The Cherno
3D Game Programming - Episode 24 - Making Our Launcher Work
The Cherno
3D Game Programming - Episode 25 - Writing and Reading Files
The Cherno
3D Game Programming - Episode 26 - Custom Resolutions
The Cherno
3D Game Programming - Episode 27 - Decorating the Launcher
The Cherno
3D Game Programming - Episode 28 - Continuing our Custom Launcher!
The Cherno
3D Game Programming - Episode 29 - Launching The Game
The Cherno
3D Game Programming - Episode 30 - Colour Processing In-Depth
The Cherno
3D Game Programming - Episode 31 - Sprites!
The Cherno
3D Game Programming - Episode 32 - Sprite Mapping
The Cherno
3D Game Programming - Episode 33 - High Resolution Rendering
The Cherno
3D Game Programming - Episode 34 - Entities
The Cherno
Genesis - My Game for Ludum Dare 24
The Cherno
Vlog + Ludum Dare Results
The Cherno
Game Programming - Episode 1 - Resolution
The Cherno
Game Programming - Episode 2 - Threads
The Cherno
Game Programming - Episode 3 - Game Loop
The Cherno
Game Programming - Episode 4 - Window
The Cherno
Episode 5 - Buffer Strategy
The Cherno
Game Programming - Episode 6 - Graphics Initialized
The Cherno
Game Programming - Episode 7 - Buffered Image and Rasters
The Cherno
Game Programming - Episode 8 - The Screen Class
The Cherno
Game Programming - Episode 9 - Rendering Pixels
The Cherno
Game Programming - Episode 10 - Clearing the Screen
The Cherno
Game Programming - Episode 11 - "Out of Bounds, Baby!"
The Cherno
Game Programming - Episode 12 - Negative Bounds
The Cherno
Game Programming - Episode 13 - Timer
The Cherno
Game Programming - Episode 14 - FPS Counter
The Cherno
Episode 15 - Tiles
The Cherno
Game Programming - Episode 16 - The Map
The Cherno
The Walls 2 - Minecraft PvP Survival Map
The Cherno
Game Programming - Episode 17 - Key Input
The Cherno
Game Programming - Episode 18 - Controlling The Map
The Cherno
Related Reads
📰
📰
📰
📰
The One-Person Billion-Dollar Company: How AI Is Rewriting the Rules of Business Forever
Medium · Startup
How I Solo-Launched a SaaS MVP in a Single Weekend
Medium · AI
7 Freelancing Lessons Nobody Tells You Before You Quit Your Job
Medium · AI
The 25% Line Item Nobody Can Explain, and It’s Killing Your EBITDA
Medium · Startup
🎓
Tutor Explanation
DeepCamp AI