Macros in C++

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey what's up guys my name is a Cherno and welcome back to my c++ series so today we're gonna be talking all about macros in c++ and we're just gonna have like a basic kind of overview of this I'm not gonna get too deep into this today we'll have some future episodes where we really dive into specifically like specific scenarios of where macros can help you out and probably some advanced examples as well but today we're just going to introduce them and talk about what they actually are so what does the C++ macro macro is is such a broad term that you could you may have heard other definitions of what a macro actually is in C++ but what I'm specifically talking about today is using the preprocessor in C++ to kind of macro fie certain operations right so instead of asked manually having to type out some kind of code over and over again we can use the preprocessor to actually help us automate that in some sense so if you don't know what the preprocessor the ears I did make a video a while back about how this people's last compiler works that covers that some extent so definitely click up there and check that out if you haven't already but basically when we compile a C++ program one of the first things that happens is a preprocessor pass occurs in which basically every every kind of statement that you see in C++ those tasks with a hash is known as a preprocessor directive that gets evaluated and kind of done right and then that code gets passed on to the compiler for the actual compilation and all of that stuff so this preprocessor stage is basically a text editing stage in which we can kind of control what code actually gets fed to the compiler and that's where macros come in what we can do is write some kind of macro that basically replaces text in our code with something else right so it's basically like going through our code and performing a find and replace and this doesn't just have to be a flat kind of just a straight find/replace it can be a fine in replace with kind of parameters and arguments and variables and all of that so we can actually kind of customize the way that we call that macro we'll define how like what it actually expands to and this can be extremely complicated we talked about templates recently and with Ted I mean the thing with that is this is this is a bit different because this doesn't happen during like templates get evaluated a bit later right in the actual compilation this is just the preprocessor and this is pure text like replacing so there's really like you can't really there's nothing you can there's nothing you can't not replace because it's it's before everything gets compiled right but what I'm kind of getting at is that there is a lot of stuff that you can actually do here and it can be really simple it can be really complicated it can be really annoying it can be really useful and the way that you use this because their boss calls itself such a powerful language the way that you use this and limit yourself is kind of going to be up to I guess your personal opinion and your personal preference I don't like overusing macros because it's very hard for people who read your code for the first time to understand what everything means and it's just not useful oh like a lot of the time don't feel with a lot of these C++ pages especially as we get into the more advanced ones there's a tendency for new program is to just really really use them a lot um and I said this in the templates video as well like that's you shouldn't be trying to do that right don't feel you have to use every single say philosophy sure to write your program like there's no point you that's not how that's not how that's not how you write good code right you're not trying to show off and right absolutely just show everyone that you know every single zip ocelots feature out there you're trying to write good code I would hope so just a little kind of precursor to this don't feel you have to use all this anyway I'm gonna I'm gonna ramble on here for hours if we don't get into some code so let's get into some code and talk about macros and how they work and all that okay so I have a very basic program here and let's think about creating our first macro so this STD syndicate is something that when I run my program will actually do is kind of pause the execution over here like this until I hit the enter key and then it actually closes my program so this line basically waits for some kind of Enter key press because it needs to read in a line from the console what we can do is instead of having to write SDC end up get every single time we can define a mapper basically just insert that code in so the way we do that is we write hash define okay this can be written anywhere by the way I'm choosing to write it up here because it's a sensible place let's just say wait and then we'll define that to be STD CN get just like that and I'm not going to define a semicolon and I'll tell you why in a minute okay now what we can do is basically get rid of this line and just type in weight followed by a semicolon okay now if I hit f5 you can see we get these SM result and two key press close everything so what I've basically done is said that whenever you encounter this symbol write the word wait I want you to paste in this code so what happens is during the preprocessor during the compilation stage and during the pre presenting stage this basically gets replaced like that and that is the code that actually gets sent to the compiler which is of course what we had before so you can see how this mapper has essentially as far as that program the way that our program runs and what our compiler sees and how it gets compiled identical compulsions don't see any difference because what we've actually done is we've just changed the way that the text kind of gets generated as it gets sent to the compiler hopefully that makes sense okay so this is super the example I've just shown you I really hope none of you ever do it because this is not this is not how you use the pre process this is silly you should write STD sandor get absolutely you should write the actual code because what happens is if this was defined in a different file right then all you would see in this file is kind of just dad right you'll see that he was to just see wait and what what on earth does why it means now this requires the programmer to actually look up the weight symbol that you've got somewhere else in your code and be like ah I see it's STD and get right you're not trying to write confusing code this isn't like some kind of obfuscation competition I hope so don't don't use the preprocessor this way anyway back to this you might have noticed that I kind of played around with a semicolon the reason I didn't put a semicolon here is because I wanted to put one here kind of makes more sense if you or semicolons here in a sense right what you can do is not put a semicolon here of course that causes a syntax error because now the code that we actually have is that and we do need a semicolon at the end of this statement and we can just move the semicolon into here make it part of the macro now you can see this looks even weirder we don't need a semicolon if we can put one here but this just evaluates to kind of being an empty statement as if it wasn't another line like this right okay few more things we don't this isn't just limited to actual statements or I mean it can be any code it can be this but it also could be something as trivial as you know a curly bracket and we could call this maybe open curly right open curly and now what we can do let's restore our seeing key over here now what we can do is replace this with open curly all right and this is looking ridiculous but if we compile and run our code of course it's going to be fine right because what it's done is when the preprocessor sees this code it will replace this open curly word with this bracket like that and we get a normal program again now that example don't use the preprocessor this way right unless you're trying to write confusing code in which case I guess this is a decent example well they probably wouldn't be calling it open curly anyway but the point is this is how the preprocessor works I'm showing you all this so that you understand how it works now let's get into maybe some useful code so another thing that you can actually do is send parameters in okay so suppose that I wanted to basically automate this kind of STD see out you know I wanted to basically just write this right so I wanted to have hello printing I didn't want to have to write esidisi out it's a bit awkward to type whoops it's a bit awkward to type because I have to type out these like less than symbols and whatever gets a bit annoying so what I'm going to do is define a macro called log that will basically log something i've written x over here and this will kind of expand to STD see out x and then end line and again I'm not writing a semicolon here because I want to have one in my actual macro now I can replace this with log hello like that and you can probably guess what's gonna happen here when the preprocessor goes through this it will basically replace log with that right and then look at this parameter and you can see x over I'm using over here right so it's going to copy and paste whatever is in here and just put it over here and so we basically just end up with this which is exactly what we want right so if I run my code right now as it is we will get holo printing to the console so this is kind of warming up towards where I might use a macro right I wouldn't really probably use long we'll see out in this fashion however in more complicated logging systems if you've got like a game engine or an application or some kind of framework you are likely to have logging systems that you want to have as macros because the way that the logging kind of is defined may change based on your configuration so let's take it let's take a look at an example of that we have two configurations right now in our program we have debug and we have released debug with is useful for debugging right that's potentially as we're developing our code as we're developing our application we want to actually run it in a way that is not optimized and potentially has extra code in there that will help us debug our actual code and so that we can like I said not optimize just so that we can like kind of go through breakpoints and actually like so the compiler doesn't transform our code to marching it in an attempt to optimize it so that we can actually debug it properly as is so anyway logging is a great example in debug mode we potentially want absolutely everything to be locked however in release mode we definitely don't want that to happen because first of all maybe release mode is our distribution build right that's what we actually distribute that's what we actually send out to people who aren't developers to our actual users we don't want that to be logging for a number of reasons maybe we don't want to give out any kind of secret information in those log files or in the actual logging meant we're printing something that we don't really want to actually print right but also performance logging takes time and we definitely don't want to be wasting time logging messages to a console during you know a user who doesn't care about that actually like playing a game or using our application so what we might actually want to do is strip all of the logging code from our actual release builds but keep them in debug builds and we can actually do that using a mapper so what I can do is if I right-click on hello world and hit properties hello world is name of my project I've got debug and release under my configurations I'm going to go into C C++ preprocessor and I'm actually going to define some thing at the front over here called debug alright now this is this may may or may not be defined based on your compiled it might be like underscore debug or something like that it may already be defined but it might not be which is why I'm showing you guys how to actually define it yourself I'm actually going to call this something like PR underscore debug PR is just gonna be two little letters that is like the name of our project it stands for project in this case but maybe if I was working on the Sparky game engine which is a game engine I wrote I might be using SP underscore debug just to basically be like this is my macro right so it doesn't kind of it's like a namespace almost so that it doesn't clash with other mappers so I've defined something in the preprocessor called PR debug and and in release I'll save this I might define something called PR release now for this example we might not need this but in other examples you may want to actually have that so what I'm going to do now is I'm going to write a basic if def if def PR underscore debug I'm going to basically include this code otherwise so else I'm going to write define log X and I'm actually not gonna put anything there just like that okay now there's plenty wrong with this code which I'll explain in a minute but that's the basic example so if PR debug is defined we're going to include this code otherwise we're going to include this card now what do you think happens when we have log X like this a macro like that and then nothing after it it's gonna replace it with nothing so what's actually gonna happen is if PR debug is not defined you can see Visual Studio is actually highlighting the one that is so if I just drop this down and change it to release mode you can see this flips this is what happens which means this gets just removed like that okay I've literally made it so that in release built I am NOT including certain code in compilation at all which is awesome because it means that that log message won't get triggered at all I'm not C outing anything which means that I get all of that slave performance back and my log message beautiful let's test this out so in debug mode just go back to debug and hit f5 you can say get the word holo printing to the console awesome and then finally I'm just going to change my configuration to release not touching the code at all just change my can duration now I hit local windows debugger on my code and check this out I get absolutely nothing printing to the console so that macro has gone ahead and basically just removed code for me that's really cool and that is actually a really good use case that is used in the real world all the time now there are certain other ones that we can actually use again for debugging purposes which you might have now actually I did say there was something's wrong with this code and I know that sometimes I end up being like hey there's playing wrong with this code but I'm not gonna tell you what it is so let me just tell you what it is first of all I'm using if def that's not great what I probably would be doing is something like if PR debug equals one and then I would actually define PR debug to be an actual value instead of actually you know defining it the thing was like defining is that if you misunderstand something with macros you can generally define symbols as either being you know define PR underscore debug or maybe define peons for the above one the benefit of doing it this way means that you can actually just put it back to zero and you don't have to actually remove the whole symbol by the commenting it or actually removing it so this is a lot more clear and if you write your code this way you can see I can actually control debug PR debug up here now you can also do this of course in the properties by just defining in debug defining PR debug to be one like that that's also totally fine and that will mean obviously if this overrides that but if I get rid of this code it actually means that will include certain code here which works pretty well the other problem here is that maybe that's not really a problem but what we also could have done is since I did define PR release we can do else L if sorry L if defined PR release like that and that would actually be you know if release might is to find a post baron release me back to debug mode then everything would be fine over there okay and I'm actually gonna go back here and fix my mistake obviously I've put spaces in here you can't do that so let's just leave it like that and hit OK and there we go that works just fine so that's basically I guess the same thing that I did before but just showing you guys another way to do it using ear frog than if defined or a depth which is slightly worse in a lot of cases anyway I'm gonna wrap off the video there because that is a pretty basic and tomorrow is actually one more thing would this if thing what you can do is disable entire blocks of code as well so I could quickly just say if the zero which means kind of if false and then wrap some code in that like that now this is now fully inactive right which means of course I get an error in this case but you can see that we can actually use preprocessor and macros I guess to actually get rid of certain things in code I've got a few more examples that I'm probably going to show in more videos there are a lot of things we can do here we can play around with like string manipulation and we can actually insert different built-in kind of preprocessor symbols such as what like file the statement is actually it kind of inserted in writing and what line of code it's happening in what function it's in and stuff like that there's a lot of stuff we can actually do mostly for debugging purposes if I have to be completely honest macros are the most useful for debugging purposes I also didn't mention that you can use backslash as if you want multi-line mappers in fact I guess I'll show you one more example what you can do is if you have something like let's just say this whole main function I want to make a macro out of this I don't have to write it all in one line just being like you know int main and then STD see and whatever that might be annoying what I can actually do is write int main and then what I actually want another line I can just add a backslash which basically escapes the newline character when I hit enter then I can write my opening curly bracket and on the backslash and then I'll write my STD seeing duck get no the backslash and then this and then I can basically replace this whole thing with main just like that and if I run my code you can see that it runs just fine as before and I can just hit enter and everything's great okay so the back slashes are basically just escaping this Enter key presses it's kind of not feeding in that entered that newline character into the pre process so that actually so that it actually keeps treating this as part of the same macro if you didn't have this then this is just kind of normal code right because macro is kind of do have to be on one line okay but backslash can prevent that make sure you don't have a space after your backslash because then you're actually escaping the space and not not the newline character so it has to be backslash and then answer straight away anyway hope that kind of explains macros to the best way to actually see these in action is to see them in action so when we start the game ends in series and we I've already used them in the OpenGL series actually check out the video about OpenGL errors that has some credit examples on how to actually use macros we use one for actually like wrapping every opengl function call in a macro so that we can arrow check it automatically every time we use in opengl function definitely check that out that's a real world example of how you might use macros when we set the game engine series as well plenty of macros will be used don't worry for stuff like memory allocation as well really useful because another example here that I might just give right now is memory with memory allocation in debug builds we might want to know exactly how many bytes are being allocated from which file and which line of code so literally like please tell me is it coming from mando CPP line 15 my allocated 28 bytes I want to know that kind of stuff right the tracking or for just debugging purposes for whatever you can actually use a macro to do that if you replace the new keyword with like a custom keyword which which will automatically actually track which line which file in line the allocation came from and how big it was and all that kind of stuff so that's another useful kind of use case for macros anyway I hope you guys enjoyed this video if you did in that like button you can also help support the series that I do here on youtube by going to patron icon for Sasha chana huge thank you as always to everyone who helps support all these videos because they wouldn't be here without all those wonderful supporters next time we're going to probably I might just dive into some more advanced map for a kind of examples actually but there are quite a lot of things that I still need to cover for the C++ series if you want to say something specific definitely leave a comment below and I will see you next time goodbye [Music]
Info
Channel: The Cherno
Views: 89,382
Rating: 4.9671168 out of 5
Keywords: thecherno, thechernoproject, cherno, c++, programming, gamedev, game development, learn c++, c++ tutorial, c++ macro, macros, define, ifdef
Id: j3mYki1SrKE
Channel Id: undefined
Length: 19min 36sec (1176 seconds)
Published: Sun Dec 17 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.