Hope you guys enjoyed the video - if you want more C++ videos let me know! Keep exploring at brilliant.org/TheCherno/ Get started for free, and hurry-the first 200 people get 20% off an annual premium subscription.
Why do i never hear you talk about Rust. Are you literally afraid to mention it's name? And why did you never talked about that the inventor of null is ashamed that it exists and that a language should actually NOT have "null". And why don't you just tell us there are languages without null and why they do that and that null should actually not exist?
I'm an old-time hardware/assembly programmer who progressed to C in the late 80's, which I found natural. In the mid 90's, I made a move to C++ and somehow just lost confidence in my ability to understand what was actually going on under the hood. As more and more features were added, I avoided them as "black magic". Your series has rekindled my confidence that it's still just bits and bytes. Thank you!
Yeah, compilers and hardware do a lot of heavy lifting and black magic. I have been screwing around with cortex-m stuff, in my cortex-m3, memory address 0 is where the program counter starts and holds the interrupt table address. I think the MCU core is hardwired to that address on a reset, the first IRQ routine is just the reset handler. I think this core has a memory protection unit, so I could set up certain memory locations that cannot be read from by non privileged code... Which triggers an MPU fault, which is handled by the ISR routine...
@@human-ft3wk as far as I can see for the people who really know what kind of instructions the compiler produces when it comes to arithmetic and memory stuff it is just way too boring and redundant to learn all those 'new' over-the-top features that make programming less fun. Might be wrong but that's my perception
there was a day where compilers didn't care if you used an uninitialized pointer and would just do undefined behavior, made some things really difficult.
Yep, i was waiting for him to explain what happens when you run it in release mode vs debug without initialising it, but it never happened. I wonder if he even knows being so young. For those wanting the answer, in release mode the variable isn't even auto initialised to 0, like it is in debug. So for his example you wouldn't even get an exception reading address 0x8 or 0x20, it will be a random value!!!!
@@aloluk 0x20 in release mode is most likely a compile time optimization of std::string. i remember strings having some really wild and weird things like negative offsets, short strings, etc
@@JakobKenda I can't reproduce this in godbolt using x64 MSVC v19.33. I only get a warning "(14) : warning C4700: uninitialized local variable 'entity' used". Maybe Cherno is using the MSVC equivalent of Werror (whatever that is, I forgot) or some other flag?
I like how you explain the mechanism instead of just saying "do this and this", what many people on youtube do. Nothing new for me, but people can actually learn from this kind of content, so props to you.
I swear to GOD that I was havning a conversation about NULL at exercism with a mentor, and came here to YT after having finished asking my question, and here the Cherno is, having upped a video about NULLs and yt recommending it after 3 mins of upload. I feel connected lol
Thanks Cherno for these videos, you’re such an amazing teacher! I hope your C++ series will cover all stuff that is used in C++ programing at some point(if thats eaven possible). It’s already one of the best places for someone to learn C++ (apart from a person coding themselves) and I think it would be amazing for someone to be able to just open your playlist and find anything they need C++ oriented.
We don't care about self at all, this may as well be a static function because we don't even use self. Sounds like a life lesson xD But there's some truth to that sadly..
@@jackytaly that's not what I said :) I liked the part where he explained why member functions that don't access member variables can be called when an instance is null.
Might be interesting to mention that C++ does not care whether or not you want to access a nullptr. It compiles fine. There is a memory management unit (MMU) in your PC that the OS will configure, usually making the first page of memory inaccessible. This is what makes reading from null an access violation. I work in embedded software with C, and before the bootloader configures the MMU, 0 is a valid address. We actually use this area of memory to store data. This is because the bootloader runs on internal CPU memory which is very limited. After initializing the external RAM we use the lowest page to store data which would not fit in the internal RAM. This is fine because the application will never be able to access this data once the MMU is configured correctly.
I would love some insight on that topic; But programs run in the os, and live in virtual memory space, not the real memory space. Unlike microcontrollers without os
@@peepeefrog_ I'm no expert on Windows, but I'd imagine it is the same way. We're not programming bare metal at my job, but we are using a real-time operating system on our microcontroller. Although for us all processes the "virtual memory" will map one-to-one to the physical memory. This allows any process to set GPIO pins with the adresses found in the datasheet for the microcontroller, for example. You could also see it as Windows not mapping the first page of virtual memory causing a violation when trying to access address 0. Maybe someone with more insight on Windows can chime in with more information.
If you want to hear something cursed, C (not sure about C++) compilers are required to give null pointers the value of 0, but their memory representation (like many representations within C) is undefined. This means that setting pointers to 0 and comparing pointers to 0 will work as expected, but only if you do so through a correct type (i.e. T*). This means for example, that calloc-ing memory to hold a pointer (or a struct containing pointers) will not necessarily give you null pointers. Same with memset, or any other way of setting the raw bytes of its value. My reading of the spec suggests that using struct foo bar = { 0 } style initializations will give the correct pointer representation. This matters generally on some old, kinda funky architectures, often because they were word addressed archs that had sizeof(char*) > sizeof(int*), as they used extra bits to encode an offset within a word. I assume it was helpful to set the leading bits of these addresses to denote that this address was longer than usual. The Tendra compiler lets you set the representation of nullpointers to 0x55555555, as I believe it's a compiler designed for finding obscure platform incompatibilities like this. See www.tendra.org/trans.1/
One of the best videos I've seen on C++. I especially liked the part that had covered the implementation of C++ classes in terms of C structs and C functions.
Me too… I never thought of it before and now it makes so much sense… like I get it now why python has self keyword.. may be it is interpreted language and can’t have compile time benefit hence they need to put this self keyword
@@siddharthchauhan1129 I agree. “self” in Python make the distinction between “member” methods and “static” methods more explicit. I mostly use C for math simulations and recently tried to implement somewhat similar to a class for a struct to hold and manipulate a dataframe in C. I mostly struggled to avoid putting this struct into the heap and retaining it in the stack to keep Python-like object.method() syntax instead of object->method() but so far failed
This series is precisely what they need to teach at Universities. Entertaining, simple but detailed, easy to follow, goes into what (at least my own) University will not go into. I had lost interest in programming due to my crappy Uni course, but thanks to Cherno, I am back and happier than ever to be programming. Thank you so kindly for making this series @The Cherno, I hope to see much more in the future!
9:21 For the record, that is only true for structs in C. In C++, structs can have functions(=methods) -- even virtual ones --, constructors, public, private and protected members, use inheritance, be templated… just like a class.
@@ΆγγελοςΤσερκέζης-ν5ε Well in C there's no concept of public and private elements as is common in OOP, so that's not a thing in C, but you can have structs that consists of both "member elements" (thats the data you'd normally put in a struct) and also function _pointers_. That means you can allocate a struct with the various data structures you'd usually do, and also have some of the types be pointers to functions. If you look up what a C function pointer looks like (which can also be a parameter to a function), it probably makes more sense.
@@master74200 well you still won't have actual methods this way since function pointers will point to static methods. That means that the function you are calling with obj.fn_pointer() won't have access to obj so can't modify any of its members (unless you explicitly provide obj as one of the function's arguments)
@@ΆγγελοςΤσερκέζης-ν5ε no no, there's a way to do it where you can call the fn ptr on the allocated struct itself and it automatically receives the a pointer to the struct as well. But honestly I don't see the big difference when every part of it is public anyway.
I hope someone has already written about null pointer in c/c++ precisely, it's not precise that "value of null is zero". Actually, at least in c and old c++, when you've written an integer constant 0 in your code which 0 is used as a pointer on the context, the 0 is INTERPRETED as a null pointer, EVEN IF the actual value which would be stored as a null pointer on memory is NOT zero. Null pointer representation on memory is one of the implementation specifics of these languages... In fact, on some (usually historic) environments, the actually stored value on the memory as a null pointer was not zero even though assigning value is 0 on the c source code (e.g. on PDP-11). But, USUALLY, the null pointer representation value is 0x00 on normally environments, including x86/amd64, arm/aarch, and mostly in use products I think, because the Application Binary Interface has already well defined to avoid the confusion. That's why that even though the offsetof() macro has (theoretically) wrong definition (at 14:55), but the macro works well; it assumes this code will be interpreted on the Microsoft's compiler -- Integer constant 0 as a pointer will be represent as 0x00 on this condition (I hope).
Great explanation. Used to argue with a coworker that NULL COULD in theory be defined as so long as it was sure to be a read access violation. 0x00 just happens to be a read violation on all platforms. But a lot of legacy code/ systems would break because many times it would simply be tested against the integer zero. I know that was quick and easy, but seems like it was mixing data types in a messy way. I always preferred to use NULL or nullptr as it keeps the proper abstraction concepts. Not so 'implementation specific'. Like using an integer value for a Boolean. If you change some details of implementation, you probably will break things. But if you stick with proper typing, much safer.
I was just looking into defining extension methods in C# and found the syntax a bit unusual. Now I totally understand why they are written the way they are. It's kinda like what you explained but in reverse. Really interesting! Thanks :))
Great presentation! I wrote an article a while ago called "how did I crash in that function?" that went through a very similar set of steps that you have here. If you haven't planned it yet, I'd suggest a follow-up for virtual/non-virtual calls and for nested member calls. Also for references since engineers can be easily convinced that a reference somehow protects you from nullptr violations.
Interesting video. Never thought about the effects of calling a method of an uninitialized variable. 2 notes for viewers. - Always initialize your raw type variables like int, float, pointers, etc. Only as members of classes its done for you. - Using uninitialized data is undefined and will not throw an error in release mode. This is one of the most occurring bugs, since you might never find out about it.
My guess about 0x8: It just assumes that the entity value is at address 0x0. The first 8 bytes of Entity (0x0 through 0x7) are the pointer to the parent entity. For C++ 0x0 is a valid memory address, so it happily returns that bit in the heap, but since we are calling ->GetName() we are actually trying to access the `string m_Name`, which starts at 0x8, since the first 8 bytes of an Entity is the parent pointer.
It would be really cool to see you cover virtual memory. covering how the operating system actually loads your code, how it manages your memory, and stuff like that could be so cool. you seem to have an above average understanding of these low level topics, which is why I am bringing it up. virtual memory is a very very VERY important concept in modern operating systems and a video about it could contain some useful information for programmers.
@@piechulla1966 Agree, but perhaps I can help a bit. Virtual memory is nothing more than an abstraction over the physical address of memory. So, the process can only access virtual addresses and they are translated on the fly by the hardware when being in use. In another way, a process will read address 1000 and the hardware will map it to a physical address (let's say 3888) and return its value. This helps in 2 things: 1. Isolation: map different physical addresses to different processes, and they all see (0 to 2^64) 2. Paging: you can use use this abstraction to map virtual addresses to your SSD Source: Tannenbaum's book Modern Operating Systems (or something similar)
@@tablettablete186 When does this come into play? Say I do: m_pSomething = new int[nNumOfNeededSomethingSlots]; // Nevermind C26409: Avoid calling new and delete explicitly, use std::make_unique instead (r.11). or std::vector vLfSomething; // .. vLfSomething.push_back(lfSomeValue); Usually I do not care what goes on behind the scenes. As long as I don't have to worry about it actually being swapped to disk (performance decline with a factor 10,000 or so for an HDD, not sure about SSDs). Seems to me that swapping to disk was interesting in the 1980ies (back then memory was very expensive) and is no longer important nowadays. Also, looks like it is turned off by default in Win 10, Win 10 IOT, and Win 11. Isn't the address space that a process is assigned by the operating system always "virtual" anyway? So many questions. I know that I know nothing. Which I mostly do not care :-)
An addition; C/C++ code halting on null pointer dereference should be considered implementation specific. You could memory map 0/null to your process if you are insane, and not all non-memory managed architectures crash on access to 0/null.
If gcc can infer that you will dereference a nullptr, it sometimes replaces the actual memory de-reference by an ud2 instruction, which is a clever way of crashing (no triggering of pagefaults, and no involvement of syscalls). This results in a SIGILL instead.
0:23 there is, but people dont like it when we do that because NULL is C and nullptr is C++. Honestly idc because C++ is basically just C with classes and namespaces lol.
They are two completely different languages at this point, they have seperate committee's and have different features. One big difference is VLA's, while C supports it C++ doesn't. Some C code can't be compiled as C++ due to reserved keywords. C++ isn't C with Classes at this point, it's an entirely different language and the way code is written in both are vastly different.
@@tri-- C++ is (mostly) backwards compatible with C, C++ supports all the same libraries, and syntactically (ignoring the additions of C++) they are extremely similar. yes, they are different languages, but one is clearly built on top of the other. because of this, programming in C++ is alot like programming in 2 languages at once.
@@ThatJay283 weird because I don't feel like I'm programming with 2 languages at once when dealing with C++. It is so different that feeling of me is gone. When I have to write some C code my mind swaps from C++ features to C stuff, to me the line between C and C++ is very solid, yes C++ is always backwards compatible and supports all compiled libraries without an abtracted header API (due to new keywords etc.) and mostly all the normal C libraries too but even when using a C library (which is often the case, GLFW and Glad are great examples) I still don't feel the way I do whenever I write C code. When dealing with the library I use C++ concepts, in C you need a function for a callback as an example but in C++ I would rather use lambdas. If a function needs a pointer parameter and it can be left invalid I pass nullptr instead of NULL. If the thing I'm dealing with is complex I'd rather abstract it to classes, if it needs memory management I could make use of RAII, all the stuff I wouldn't even think about when writing C code.
The standard does not specify that nullptr has to refer to the address 0. It only says that the literal value of 0, in a pointer context, must be interpreted by the compiler as nullptr. Therefore 0 *can* be a valid memory address.
Super helpful video. You also inadvertently explained why rust methods take in 'self' as the first parameter. Turns out C++ had been doing it for years and just never told you
Love this video, because you never answer JUST the question from the beginning. I never even would've considered that stuff about "offsetof" and when you CAN use a nullptr, but now I do! I think it's SO important in a language like C++ to explain some of the rules, and then ALSO explain all the exceptions to the rule; those exceptions really help you understand the core idea, not a specific problem.
Man... I literally missed you. The last videos I saw from your channel were OpenGL series from 5 years ago! I'm not sure how YT suggested a video while I wasn't subscribing, but man, you got older :) Keep it up my friend...
This was a great video. I am, for the most part, self taught when it comes to c++ programming. That is to say, I've been through books and tutorials but my knowledge of real world application is zero. However, Cherno's videos are still enlightening and very interesting to watch, even if I will never find myself applying this outside of a hobbiest's interest. Thanks for the video.
Thank you! I'm new to C++ and this series has been super helpful. If I may suggest an idea, could you make a video on how to read data from a gzipped file line by line regardless of how long the lines are?
NULL is not nullptr, one is a int with the value of 0, the other is a ptr to the zeroth position in memory. It makes a important distinction for some fct overloading handling since the type is not the same!
nullptr is not a pointer tho 😏 It is an object that can be casted to a pointer of any pointer type, and the value of that pointer would be 0. And on some systems, NULL is also a pointer, and not a number, probably a void* or some compiller intrinsic value, that is treated as a memory address
clicked on this video to get the answer that was explained in the first minute or so. So glad I stayed, very interesting. The funny thing is I don't see how this knowledge is going to help me with my work but I'm still glad to know it. Hope you do more videos like this. The information was very concise and well explained :)
I don't know if it can help with your work but one thing this knowledge can give you is how to hack into classes. Suppose that you are given a class A { private: int value; }; and you can reinterpret_cast it to class A_hacked { private: int value; public: int get_value() { return value; } }; which you can use to get the value.
Pointers, even if they are double, triple and so on, always seemed so easy. You allocate stuff, you de-allocate stuff and do null checks. Don't know why most high level languages don't provide pointers but I guess it's to avoid boilerplate code and/or errors that come from mishandling them
That’s why the typical java null pointer exception felt so wrong for me as a C++ dev, the problem is never to use a null pointer, the problem is using the memory pointed by a null pointer.
At 12:50 "It's not like this function exists 'within' the actual Entity class. It's not physically existing inside here". I think talking about the physical existence of functions is kinda dope. Funny how the brain creates a different reality - or should I say a separat mental model for source code. Just as we have a mental model of the physical world around us.
@@ohwow2074 forgive me if i’m wrong (i come from a java background), but can’t we try initializing so many nested pointers that ultimately point to 0x0, and the offset from these pointer locations add up to a valid location?
@@Sandeep-cz7ls I'm not sure what you mean by nested pointers, but if it is a member variable of a class that points to another member of the same class, that still only adds 8 bytes total to the class. The next pointer is located at a potentially completely different location in memory.
NULL is NOT defined as zero per the specification, but is SPECIFICALLY implementation-defined. It may be zero, or it may be some implementation of a nullptr system, or it may do something different.
This raises the question: How do you write to address zero when necessary? Let's say I'm on an embedded system and some hardware (maybe ram) is located/starts right at adress zero on the bus, how to read/write to it? Is it like a convention to never actually hook something to adress zero on the bus?
Nice explanation about member functions living separate from the data structure storage. Now.... about 'virtual functions' and the virtual function pointer table???? That could use a good video as well. (hint...hint... hint...)
I kid you not.. after I learn things from you.. I sure sound really smart in front of my colleagues.. your explanations are so precise and cover very critical points..
There's a physical address zero but it is always reserved by the operating system, and also the operating system most likely nowadays doesn't allow you to use direct addressing anyway, so the virtual address tables that the OS uses probably doesn't have a zero entry.
I work as C++ dev and I thought that nothing will surprise me in your movie, but I was wrong! I've never tried calling 'empty' method on nullptr. Didn't expect that.
to be exact: the WHOLE FIRST MEMORY PAGE (including the address 0) is an invalid memory address space. In this example we weren't accessing the data at memory 0, we were accessing the data from memory address 8 which is not null. But because the whole page is invalid (it's size is probably 4kbytes), the programm failes. It's possible because of the Memory Management Unit (MMU) that's a part of the cpu and is controlled by the os. It acts as a lookup table of memory pages; the os sets this page for each process. Next, then you access some memory from your programm, you don't actually access it from the exact physical address, that you're trying to reach. Instead this call goes through MMU, that redirects it to the exact physical memory page. Thus the virtual memory is achieved. But what if the os mappes our page 0 to an invalid page through the MMU? The page becomes unaccessable and any read\write attempt would trigger a hardware error, which is then repored to the os, almost like an exception. So, the os is responsible for mapping pages for each process, and it mappes the 0'th page to an invalid page. BUT it doesn't have to. IT IS POSSIBLE to map the 0'th page to some actual physical memory page. That would allow us to use nullptr as an actual working memory address. But that would break a lot of stuff, that relies on the nullptr being an invalid address, so nobody does that in practise
It isn't only like a exception, it is in fact exception, first 32 interrupts handlers are called exceptions or also faults. And mmu isn't really controlled by the OS, it is controlled by the cpu, os only provides page table for it. Btw every address that isn't mapped to the process by OS is invalid not only 0th page
Is there a possibility of a nasty intermittent bug there in code that happens to define a large enough struct type? If you had a pointer to that struct type, which happened to be null when you accessed one of its members, and the struct was so large that the offset of that member took you all the way from 0x0 up into valid memory, then the code might run on some random data that it happened to find at 0x0 + offsetof(member). 😱...all of a sudden the flight controls are responding to the media volume set by the passenger in seat 12A. Nah, that could never happen.
On 32 bit systems this might possibly happen, and your program would just crash anyway because you're reading garbage data. On a 64 bit system however, between 0x0 and valid memory there is exabytes of memory, and good luck making a struct that big. I am not surprised if the compiler would just refuse to compile that. And if it doesn't, your program will crash ass soon as you attempt to use it in any way. On an airplane all of the systems run on completely separate computers.
Hi Cherno awesome video! Please keep on making C++ videos. They are the best ones outthere. Also your Walnut video and repository is gold for unexperienced hobby programmers like me. If you would ever show how to port an app built on your Walnut framework to Mac that would make me veery happy :) have a good one... cheers
He did not explain why NULL is literally a mistake in languages who have it. And that NULL has costed billions and billions of dollars. There is a clear reason why Rust for example has no NULL. Even the inventor of NULL is ashamed for it and said it is his biggest mistake and said it should not exist. Null should not exist.
This kind of thing also is why C cannot easily call into C++: features like templates, vtables, etc do not translate into most calling conventions and thus cannot be outputted by the compiler.
To make it short NULL is the billion dollar bug ! When you follow the inventor of it Tony Hoare who put it in the first time in a programming language when ghetto build the Algol 68 compiler. It was just a easy solution to get around compiler checks at every pointer usage. As far as I know only one programming language has got rid of having null pointers Scala 3. The problem also is that a pointer by definition is set to an arbitrary value if not explicitly set to which points to some random memory area, which leads to much more hard to debug errors. Tony Hoare was right it's a billion dollar but use something that works instead.
There is a difference between NULL and nullptr in c++ The issue comes with function overloading Say you have 2 functions with the same name void doSomething(int n); void doSomething (int* n); One takes in a type Int The other type Int pointer So what happens when you call doSomething (NULL) vs doSomething (nullptr)? The NULL is going to call the first function and nullptr is going to call the second function This might be an issue if you are not careful with the difference between them.
2:04 Regarding why it's considered poor form to explicitly write 0 or (void *)0 for NULL/nullptr, the word "portability" rings in my head like an obnoxious bell. If hearsay serves me well, the actual memory address for null is (strictly speaking) implementation defined: I.E. You might find some funky machines, whose null addresses are somewhere other than 0.
I like how he explained the class with struct, like class functions are free floating functions with that entity* as the parameter, like this in Java, that's why cpp is more efficient when it comes to memory management
Java is memory inefficient because of: * EVERYTHING is allocated on the heap * Your code runs in JVM that runs natively. So, in a way, your code runs twice Most of things mentioned above are mitigated by using some smart tricks in every new version of Java. So modern Java is not that slow but still slower than C++ in most cases.
@@igorthelight Yes, they are trying to implement python features in their updates. Is there any specific reason behind this memory thing in Java? So my teacher said that, Java is programmer friendly so it takes care of memory allocations by itself that's why unlike cpp we can't play with memory related stuffs in Java, is there any other specific reason for this?
@@Its.all.goodman I don't know another reason for that. Probably, it's just easier for everything being on the heap for JVM. C#, for example, have proper stack allocation and a heap allocation. But it doesn't have a "true" VM. It's "CLR" is what it uses instead of a VM - it's faster but not as cross platform by default as JVM. My opinion - if you need a more C++ like language - C# is better that Java in that case (it has GOTO, pointer operations and native integers which are faster). Java is more cross platform tho ;-) So that's why noone could say that some language is the best xD
Hope you guys enjoyed the video - if you want more C++ videos let me know! Keep exploring at brilliant.org/TheCherno/ Get started for free, and hurry-the first 200 people get 20% off an annual premium subscription.
Why do i never hear you talk about Rust. Are you literally afraid to mention it's name? And why did you never talked about that the inventor of null is ashamed that it exists and that a language should actually NOT have "null". And why don't you just tell us there are languages without null and why they do that and that null should actually not exist?
@@HermanWillems Calm down mate, calm down...
@@TheMR-777 oh i dont mean things personal. Im dutch im quite direct. Sorry if it sounds personal its not. I just had some questions.
@@HermanWillems Oh alright :)
It's fine.
Yes more cpp videos obviously
I'm an old-time hardware/assembly programmer who progressed to C in the late 80's, which I found natural. In the mid 90's, I made a move to C++ and somehow just lost confidence in my ability to understand what was actually going on under the hood. As more and more features were added, I avoided them as "black magic". Your series has rekindled my confidence that it's still just bits and bytes. Thank you!
Yeah, compilers and hardware do a lot of heavy lifting and black magic. I have been screwing around with cortex-m stuff, in my cortex-m3, memory address 0 is where the program counter starts and holds the interrupt table address. I think the MCU core is hardwired to that address on a reset, the first IRQ routine is just the reset handler. I think this core has a memory protection unit, so I could set up certain memory locations that cannot be read from by non privileged code... Which triggers an MPU fault, which is handled by the ISR routine...
C++ does feel a little complex. I would recommend going for Rust. It is in every way a successor.
If you can’t do, become an expert in what you know and teach.
Also keep learning!!!
@@human-ft3wk as far as I can see for the people who really know what kind of instructions the compiler produces when it comes to arithmetic and memory stuff it is just way too boring and redundant to learn all those 'new' over-the-top features that make programming less fun. Might be wrong but that's my perception
C++ isn't even my main language, but holy moly you learn so much from these deep dive videos it's insane.
Keep up the amazing video quality Yan
yeah, i come from the land of python and i just learnt huge loads of stuff that can help me improve my python classes
Oh, I'm staying there for a while! Can you recommend any nice places to visit?
C++ isn't my main language as well, my main one is Russian
Understanding pointers is useful in a lot of languages!
I miss the c++ series so much every one is a banger
Why do you miss it? It's still there!
@@flflflflflfl Because he isn't continuing it
@@elektra81516 do you "miss" half life because there was never a part 3?
@@flflflflflfl well yes that’s the point
there was a day where compilers didn't care if you used an uninitialized pointer and would just do undefined behavior, made some things really difficult.
Yep, i was waiting for him to explain what happens when you run it in release mode vs debug without initialising it, but it never happened. I wonder if he even knows being so young.
For those wanting the answer, in release mode the variable isn't even auto initialised to 0, like it is in debug. So for his example you wouldn't even get an exception reading address 0x8 or 0x20, it will be a random value!!!!
GCC still doesn't care. It does give a warning but only if you run it with -Wall. Same with Clang, I guess only MSVC gives an error.
@@aloluk I can't imagine he does not know this. He's been a professional software developer for years at EA.
@@aloluk 0x20 in release mode is most likely a compile time optimization of std::string. i remember strings having some really wild and weird things like negative offsets, short strings, etc
@@JakobKenda I can't reproduce this in godbolt using x64 MSVC v19.33. I only get a warning "(14) : warning C4700: uninitialized local variable 'entity' used". Maybe Cherno is using the MSVC equivalent of Werror (whatever that is, I forgot) or some other flag?
I like how you explain the mechanism instead of just saying "do this and this", what many people on youtube do. Nothing new for me, but people can actually learn from this kind of content, so props to you.
yeah, i really was not expecting this deep of an explanation. while i did already know this it was still good to see.
I swear to GOD that I was havning a conversation about NULL at exercism with a mentor, and came here to YT after having finished asking my question, and here the Cherno is, having upped a video about NULLs and yt recommending it after 3 mins of upload. I feel connected lol
Things like this happened to me as well
Thanks Cherno for these videos, you’re such an amazing teacher! I hope your C++ series will cover all stuff that is used in C++ programing at some point(if thats eaven possible). It’s already one of the best places for someone to learn C++ (apart from a person coding themselves) and I think it would be amazing for someone to be able to just open your playlist and find anything they need C++ oriented.
12:33 "We don't care about self, at all." That got dark suddenly 🤣
We don't care about self at all, this may as well be a static function because we don't even use self.
Sounds like a life lesson xD
But there's some truth to that sadly..
Dude seriously after 10 years of working in C++ you keep giving me so much input about stuff I didn't know before. keep going.
you’ve made it 10 years without knowing what null is? props to you
@@jackytaly that's not what I said :) I liked the part where he explained why member functions that don't access member variables can be called when an instance is null.
@@giantsue Still though... memory layout is pretty much a core concept that you ought to have learned very early on
@@jbird4478 happy for you if you did, I didn't.
@@giantsue It's hard to believe you are 10 years c++ programmer lacking so many basics...
Might be interesting to mention that C++ does not care whether or not you want to access a nullptr. It compiles fine. There is a memory management unit (MMU) in your PC that the OS will configure, usually making the first page of memory inaccessible. This is what makes reading from null an access violation.
I work in embedded software with C, and before the bootloader configures the MMU, 0 is a valid address. We actually use this area of memory to store data. This is because the bootloader runs on internal CPU memory which is very limited. After initializing the external RAM we use the lowest page to store data which would not fit in the internal RAM. This is fine because the application will never be able to access this data once the MMU is configured correctly.
I would love some insight on that topic;
But programs run in the os, and live in virtual memory space, not the real memory space. Unlike microcontrollers without os
@@peepeefrog_ I'm no expert on Windows, but I'd imagine it is the same way. We're not programming bare metal at my job, but we are using a real-time operating system on our microcontroller. Although for us all processes the "virtual memory" will map one-to-one to the physical memory. This allows any process to set GPIO pins with the adresses found in the datasheet for the microcontroller, for example.
You could also see it as Windows not mapping the first page of virtual memory causing a violation when trying to access address 0.
Maybe someone with more insight on Windows can chime in with more information.
If you want to hear something cursed, C (not sure about C++) compilers are required to give null pointers the value of 0, but their memory representation (like many representations within C) is undefined. This means that setting pointers to 0 and comparing pointers to 0 will work as expected, but only if you do so through a correct type (i.e. T*).
This means for example, that calloc-ing memory to hold a pointer (or a struct containing pointers) will not necessarily give you null pointers. Same with memset, or any other way of setting the raw bytes of its value. My reading of the spec suggests that using struct foo bar = { 0 } style initializations will give the correct pointer representation.
This matters generally on some old, kinda funky architectures, often because they were word addressed archs that had sizeof(char*) > sizeof(int*), as they used extra bits to encode an offset within a word. I assume it was helpful to set the leading bits of these addresses to denote that this address was longer than usual. The Tendra compiler lets you set the representation of nullpointers to 0x55555555, as I believe it's a compiler designed for finding obscure platform incompatibilities like this. See www.tendra.org/trans.1/
Dude I literally love your videos. Even just you showing how you can inspect the physical memory like that?? Never knew that and that's sooo cool.
One of the best videos I've seen on C++. I especially liked the part that had covered the implementation of C++ classes in terms of C structs and C functions.
Me too… I never thought of it before and now it makes so much sense… like I get it now why python has self keyword.. may be it is interpreted language and can’t have compile time benefit hence they need to put this self keyword
@@siddharthchauhan1129 I agree. “self” in Python make the distinction between “member” methods and “static” methods more explicit. I mostly use C for math simulations and recently tried to implement somewhat similar to a class for a struct to hold and manipulate a dataframe in C. I mostly struggled to avoid putting this struct into the heap and retaining it in the stack to keep Python-like object.method() syntax instead of object->method() but so far failed
@@alex_8704
#define -> .
Would that even work? xD
@@igorthelight In terms of "#define" my idea was rather to "#define . ->" , but it would have ruined all other dots in my code.
@@alex_8704 True xD
Still the best C++ series out there! Could you please make a video about files in C++ ?
This series is precisely what they need to teach at Universities. Entertaining, simple but detailed, easy to follow, goes into what (at least my own) University will not go into. I had lost interest in programming due to my crappy Uni course, but thanks to Cherno, I am back and happier than ever to be programming. Thank you so kindly for making this series @The Cherno, I hope to see much more in the future!
Great work Cherno! C++videos is a masterpiece, hope you can keep producing it !!!
9:21 For the record, that is only true for structs in C. In C++, structs can have functions(=methods) -- even virtual ones --, constructors, public, private and protected members, use inheritance, be templated… just like a class.
They can in C as well, but it's a bit... Weird.
@@master74200??
@@ΆγγελοςΤσερκέζης-ν5ε Well in C there's no concept of public and private elements as is common in OOP, so that's not a thing in C, but you can have structs that consists of both "member elements" (thats the data you'd normally put in a struct) and also function _pointers_. That means you can allocate a struct with the various data structures you'd usually do, and also have some of the types be pointers to functions. If you look up what a C function pointer looks like (which can also be a parameter to a function), it probably makes more sense.
@@master74200 well you still won't have actual methods this way since function pointers will point to static methods. That means that the function you are calling with obj.fn_pointer() won't have access to obj so can't modify any of its members (unless you explicitly provide obj as one of the function's arguments)
@@ΆγγελοςΤσερκέζης-ν5ε no no, there's a way to do it where you can call the fn ptr on the allocated struct itself and it automatically receives the a pointer to the struct as well. But honestly I don't see the big difference when every part of it is public anyway.
I hope someone has already written about null pointer in c/c++ precisely, it's not precise that "value of null is zero".
Actually, at least in c and old c++,
when you've written an integer constant 0 in your code which 0 is used as a pointer on the context,
the 0 is INTERPRETED as a null pointer, EVEN IF the actual value which would be stored as a null pointer on memory is NOT zero.
Null pointer representation on memory is one of the implementation specifics of these languages...
In fact, on some (usually historic) environments,
the actually stored value on the memory as a null pointer was not zero even though assigning value is 0 on the c source code (e.g. on PDP-11).
But, USUALLY, the null pointer representation value is 0x00 on normally environments,
including x86/amd64, arm/aarch, and mostly in use products I think,
because the Application Binary Interface has already well defined to avoid the confusion.
That's why that even though the offsetof() macro has (theoretically) wrong definition (at 14:55), but the macro works well;
it assumes this code will be interpreted on the Microsoft's compiler -- Integer constant 0 as a pointer will be represent as 0x00 on this condition (I hope).
that's why the offsetof macro has multiple definitions, you can even see it in his video.
I usually get kind of lost in your videos 'cause they a bit advanced for me. But this one was at an epiphany level. So clear and reachable. Thank you
Great explanation. Used to argue with a coworker that NULL COULD in theory be defined as so long as it was sure to be a read access violation. 0x00 just happens to be a read violation on all platforms. But a lot of legacy code/ systems would break because many times it would simply be tested against the integer zero. I know that was quick and easy, but seems like it was mixing data types in a messy way. I always preferred to use NULL or nullptr as it keeps the proper abstraction concepts. Not so 'implementation specific'.
Like using an integer value for a Boolean. If you change some details of implementation, you probably will break things. But if you stick with proper typing, much safer.
I was just looking into defining extension methods in C# and found the syntax a bit unusual. Now I totally understand why they are written the way they are. It's kinda like what you explained but in reverse. Really interesting! Thanks :))
Great presentation! I wrote an article a while ago called "how did I crash in that function?" that went through a very similar set of steps that you have here. If you haven't planned it yet, I'd suggest a follow-up for virtual/non-virtual calls and for nested member calls. Also for references since engineers can be easily convinced that a reference somehow protects you from nullptr violations.
holy crap this is awesome, you just became one of my favorite programming youtubers
Interesting video. Never thought about the effects of calling a method of an uninitialized variable.
2 notes for viewers.
- Always initialize your raw type variables like int, float, pointers, etc. Only as members of classes its done for you.
- Using uninitialized data is undefined and will not throw an error in release mode. This is one of the most occurring bugs, since you might never find out about it.
My guess about 0x8: It just assumes that the entity value is at address 0x0. The first 8 bytes of Entity (0x0 through 0x7) are the pointer to the parent entity.
For C++ 0x0 is a valid memory address, so it happily returns that bit in the heap, but since we are calling ->GetName() we are actually trying to access the `string m_Name`, which starts at 0x8, since the first 8 bytes of an Entity is the parent pointer.
I'd just correct the part you said it "assumed" the entity was at 0x0.
The code explicitly set the object address to 0x0, no guesses were made.
As an Embedded C dev, this episode helped me a lot to understand C++. Thank you
Sorry but how much do you earn monthly?
It would be really cool to see you cover virtual memory. covering how the operating system actually loads your code, how it manages your memory, and stuff like that could be so cool. you seem to have an above average understanding of these low level topics, which is why I am bringing it up. virtual memory is a very very VERY important concept in modern operating systems and a video about it could contain some useful information for programmers.
If your application really gets into this situation, you should rather buy additional main memory.
@@piechulla1966 What? Virtual memory is not just important to use with paging, it is also useful to isolate processes.
@@tablettablete186 The definition(s) of "virtual memory" are not entirely clear to me now. Cherno should perhaps really take on the topic 🙂
@@piechulla1966 Agree, but perhaps I can help a bit.
Virtual memory is nothing more than an abstraction over the physical address of memory.
So, the process can only access virtual addresses and they are translated on the fly by the hardware when being in use.
In another way, a process will read address 1000 and the hardware will map it to a physical address (let's say 3888) and return its value.
This helps in 2 things:
1. Isolation: map different physical addresses to different processes, and they all see (0 to 2^64)
2. Paging: you can use use this abstraction to map virtual addresses to your SSD
Source: Tannenbaum's book Modern Operating Systems (or something similar)
@@tablettablete186 When does this come into play? Say I do:
m_pSomething = new int[nNumOfNeededSomethingSlots]; // Nevermind C26409: Avoid calling new and delete explicitly, use std::make_unique instead (r.11).
or
std::vector vLfSomething;
// ..
vLfSomething.push_back(lfSomeValue);
Usually I do not care what goes on behind the scenes. As long as I don't have to worry about it actually being swapped to disk (performance decline with a factor 10,000 or so for an HDD, not sure about SSDs).
Seems to me that swapping to disk was interesting in the 1980ies (back then memory was very expensive) and is no longer important nowadays. Also, looks like it is turned off by default in Win 10, Win 10 IOT, and Win 11.
Isn't the address space that a process is assigned by the operating system always "virtual" anyway?
So many questions. I know that I know nothing. Which I mostly do not care :-)
An addition; C/C++ code halting on null pointer dereference should be considered implementation specific. You could memory map 0/null to your process if you are insane, and not all non-memory managed architectures crash on access to 0/null.
If gcc can infer that you will dereference a nullptr, it sometimes replaces the actual memory de-reference by an ud2 instruction, which is a clever way of crashing (no triggering of pagefaults, and no involvement of syscalls). This results in a SIGILL instead.
0:23 there is, but people dont like it when we do that because NULL is C and nullptr is C++. Honestly idc because C++ is basically just C with classes and namespaces lol.
They are two completely different languages at this point, they have seperate committee's and have different features. One big difference is VLA's, while C supports it C++ doesn't. Some C code can't be compiled as C++ due to reserved keywords. C++ isn't C with Classes at this point, it's an entirely different language and the way code is written in both are vastly different.
@@tri-- C++ is (mostly) backwards compatible with C, C++ supports all the same libraries, and syntactically (ignoring the additions of C++) they are extremely similar. yes, they are different languages, but one is clearly built on top of the other. because of this, programming in C++ is alot like programming in 2 languages at once.
@@ThatJay283 weird because I don't feel like I'm programming with 2 languages at once when dealing with C++. It is so different that feeling of me is gone. When I have to write some C code my mind swaps from C++ features to C stuff, to me the line between C and C++ is very solid, yes C++ is always backwards compatible and supports all compiled libraries without an abtracted header API (due to new keywords etc.) and mostly all the normal C libraries too but even when using a C library (which is often the case, GLFW and Glad are great examples) I still don't feel the way I do whenever I write C code. When dealing with the library I use C++ concepts, in C you need a function for a callback as an example but in C++ I would rather use lambdas. If a function needs a pointer parameter and it can be left invalid I pass nullptr instead of NULL. If the thing I'm dealing with is complex I'd rather abstract it to classes, if it needs memory management I could make use of RAII, all the stuff I wouldn't even think about when writing C code.
Just 2?
The standard does not specify that nullptr has to refer to the address 0. It only says that the literal value of 0, in a pointer context, must be interpreted by the compiler as nullptr.
Therefore 0 *can* be a valid memory address.
Cherno, you are one amazing human being. Thank you so much for making these videos, they are truly awesome!
Super helpful video. You also inadvertently explained why rust methods take in 'self' as the first parameter. Turns out C++ had been doing it for years and just never told you
Love this video, because you never answer JUST the question from the beginning. I never even would've considered that stuff about "offsetof" and when you CAN use a nullptr, but now I do! I think it's SO important in a language like C++ to explain some of the rules, and then ALSO explain all the exceptions to the rule; those exceptions really help you understand the core idea, not a specific problem.
I was watching the original Cpp videos from 6 years ago and suddenly stumbled on to this video. Wooohhh, Dude has changed so much😀. I love it.
Man... I literally missed you. The last videos I saw from your channel were OpenGL series from 5 years ago! I'm not sure how YT suggested a video while I wasn't subscribing, but man, you got older :)
Keep it up my friend...
This was a great video. I am, for the most part, self taught when it comes to c++ programming. That is to say, I've been through books and tutorials but my knowledge of real world application is zero. However, Cherno's videos are still enlightening and very interesting to watch, even if I will never find myself applying this outside of a hobbiest's interest. Thanks for the video.
This is genuinely super interesting and gives lots of insights into how C++ works under the hood
16:45 THIS MAKES SOO MUCH SENSE! Wow. I love C++
Damn I hate people who just praise contents in comments without any added value. But this is some huge quality work! Very instructive!!!!!!
Thank you! I'm new to C++ and this series has been super helpful. If I may suggest an idea, could you make a video on how to read data from a gzipped file line by line regardless of how long the lines are?
Read about «stream»
WOW, this is one of your best explanations ever. Thanks alot for making me understand it fully :)
NULL is not nullptr, one is a int with the value of 0, the other is a ptr to the zeroth position in memory.
It makes a important distinction for some fct overloading handling since the type is not the same!
nullptr is not a pointer tho 😏 It is an object that can be casted to a pointer of any pointer type, and the value of that pointer would be 0. And on some systems, NULL is also a pointer, and not a number, probably a void* or some compiller intrinsic value, that is treated as a memory address
clicked on this video to get the answer that was explained in the first minute or so. So glad I stayed, very interesting. The funny thing is I don't see how this knowledge is going to help me with my work but I'm still glad to know it. Hope you do more videos like this. The information was very concise and well explained :)
I don't know if it can help with your work but one thing this knowledge can give you is how to hack into classes. Suppose that you are given a class A { private: int value; }; and you can reinterpret_cast it to class A_hacked { private: int value; public: int get_value() { return value; } }; which you can use to get the value.
i can't imagine that i actually have an java exam tomorrow and i'm here watching this c++ video because of how great it is
how was the exam bro?
Now to complete this, do virtual functions and how vtables fit into memory layout of objects. . And how the pack pragma affects these values in msvc.
Pointers, even if they are double, triple and so on, always seemed so easy. You allocate stuff, you de-allocate stuff and do null checks.
Don't know why most high level languages don't provide pointers but I guess it's to avoid boilerplate code and/or errors that come from mishandling them
That’s why the typical java null pointer exception felt so wrong for me as a C++ dev, the problem is never to use a null pointer, the problem is using the memory pointed by a null pointer.
The C standard actually allows for the internal representation of a null pointer to be nonzero.
This video is gold in the context of understanding "this". Thanks!
Not only null, but my concepts of structs, classes and memory address allocation were all cleared. Thank you.
You absolute legend, you just saved a project I’ve had on the to-do list
What theme are you using??
At 12:50 "It's not like this function exists 'within' the actual Entity class. It's not physically existing inside here".
I think talking about the physical existence of functions is kinda dope.
Funny how the brain creates a different reality - or should I say a separat mental model for source code. Just as we have a mental model of the physical world around us.
this is so educational omg the way you connected the dots, great work!!
This was amazing, thanks for sharing. Knowing deep down how things ACTUALLY work makes a big difference.
Interresting! What font are you using? It looks clean
Imagine if you had a class so large that when you access the offset of a member variable, it ends up being inside valid memory.
How would you store the object in the memory in the first place? I think what you said doesn't make sense since it probably can't happen.
@@ohwow2074 forgive me if i’m wrong (i come from a java background), but can’t we try initializing so many nested pointers that ultimately point to 0x0, and the offset from these pointer locations add up to a valid location?
@@Sandeep-cz7ls I'm not sure what you mean by nested pointers, but if it is a member variable of a class that points to another member of the same class, that still only adds 8 bytes total to the class. The next pointer is located at a potentially completely different location in memory.
a class with millions of members... sounds intense
@@bluesillybeard Arrays can puff up your class sizes in no time.
Priceless explanation!!!
Hello Cherno,
I really like the way you teach. Could you please make a tutorial on design patterns
NULL is NOT defined as zero per the specification, but is SPECIFICALLY implementation-defined. It may be zero, or it may be some implementation of a nullptr system, or it may do something different.
This raises the question: How do you write to address zero when necessary? Let's say I'm on an embedded system and some hardware (maybe ram) is located/starts right at adress zero on the bus, how to read/write to it? Is it like a convention to never actually hook something to adress zero on the bus?
thankyou. that gived me a new understanding of C++ and compiled programming languages and how they work
Could've used Godbolts Compiler Explorer to showcase what actually happens under the hood as well.
Nice explanation about member functions living separate from the data structure storage. Now.... about 'virtual functions' and the virtual function pointer table???? That could use a good video as well. (hint...hint... hint...)
A video on this would be great!
I kid you not.. after I learn things from you.. I sure sound really smart in front of my colleagues.. your explanations are so precise and cover very critical points..
There's a physical address zero but it is always reserved by the operating system, and also the operating system most likely nowadays doesn't allow you to use direct addressing anyway, so the virtual address tables that the OS uses probably doesn't have a zero entry.
Your videos are so helpful. Thank you man.
I work as C++ dev and I thought that nothing will surprise me in your movie, but I was wrong! I've never tried calling 'empty' method on nullptr. Didn't expect that.
these kind of video will keep my foundation even more strong
to be exact: the WHOLE FIRST MEMORY PAGE (including the address 0) is an invalid memory address space. In this example we weren't accessing the data at memory 0, we were accessing the data from memory address 8 which is not null. But because the whole page is invalid (it's size is probably 4kbytes), the programm failes. It's possible because of the Memory Management Unit (MMU) that's a part of the cpu and is controlled by the os. It acts as a lookup table of memory pages; the os sets this page for each process. Next, then you access some memory from your programm, you don't actually access it from the exact physical address, that you're trying to reach. Instead this call goes through MMU, that redirects it to the exact physical memory page. Thus the virtual memory is achieved. But what if the os mappes our page 0 to an invalid page through the MMU? The page becomes unaccessable and any read\write attempt would trigger a hardware error, which is then repored to the os, almost like an exception. So, the os is responsible for mapping pages for each process, and it mappes the 0'th page to an invalid page. BUT it doesn't have to. IT IS POSSIBLE to map the 0'th page to some actual physical memory page. That would allow us to use nullptr as an actual working memory address. But that would break a lot of stuff, that relies on the nullptr being an invalid address, so nobody does that in practise
It isn't only like a exception, it is in fact exception, first 32 interrupts handlers are called exceptions or also faults. And mmu isn't really controlled by the OS, it is controlled by the cpu, os only provides page table for it. Btw every address that isn't mapped to the process by OS is invalid not only 0th page
And btw page fault isn't hardware error
This was an important video and I think you nailed it. Well done.
Is there a possibility of a nasty intermittent bug there in code that happens to define a large enough struct type?
If you had a pointer to that struct type, which happened to be null when you accessed one of its members, and the struct was so large that the offset of that member took you all the way from 0x0 up into valid memory, then the code might run on some random data that it happened to find at 0x0 + offsetof(member).
😱...all of a sudden the flight controls are responding to the media volume set by the passenger in seat 12A. Nah, that could never happen.
On 32 bit systems this might possibly happen, and your program would just crash anyway because you're reading garbage data.
On a 64 bit system however, between 0x0 and valid memory there is exabytes of memory, and good luck making a struct that big. I am not surprised if the compiler would just refuse to compile that. And if it doesn't, your program will crash ass soon as you attempt to use it in any way.
On an airplane all of the systems run on completely separate computers.
I remember trying find out why a null check on a string isn't being triggered. Turn out the string was "null"
Hi Cherno awesome video! Please keep on making C++ videos. They are the best ones outthere.
Also your Walnut video and repository is gold for unexperienced hobby programmers like me. If you would ever show how to port an app built on your Walnut framework to Mac that would make me veery happy :)
have a good one... cheers
Best explanation of null I've ever seen. Your videos are clear and on point. Love it.
He did not explain why NULL is literally a mistake in languages who have it. And that NULL has costed billions and billions of dollars. There is a clear reason why Rust for example has no NULL. Even the inventor of NULL is ashamed for it and said it is his biggest mistake and said it should not exist. Null should not exist.
I’ve worked on systems where 0 is valid memory address before. It’s best to use things like nullptr and NULL over a hardcoded number when possible.
This was really deep, before I saw the video I thought I knew what null really is and just watched it for fun,
good job Cherno 👌👌
this is one of the best yt videos i've ever seen
This kind of thing also is why C cannot easily call into C++: features like templates, vtables, etc do not translate into most calling conventions and thus cannot be outputted by the compiler.
To make it short NULL is the billion dollar bug !
When you follow the inventor of it Tony Hoare who put it in the first time in a programming language when ghetto build the Algol 68 compiler. It was just a easy solution to get around compiler checks at every pointer usage.
As far as I know only one programming language has got rid of having null pointers Scala 3.
The problem also is that a pointer by definition is set to an arbitrary value if not explicitly set to which points to some random memory area, which leads to much more hard to debug errors.
Tony Hoare was right it's a billion dollar but use something that works instead.
There is a difference between NULL and nullptr in c++
The issue comes with function overloading
Say you have 2 functions with the same name
void doSomething(int n);
void doSomething (int* n);
One takes in a type Int
The other type Int pointer
So what happens when you call
doSomething (NULL) vs doSomething (nullptr)?
The NULL is going to call the first function and nullptr is going to call the second function
This might be an issue if you are not careful with the difference between them.
Nice point. I didn't know that. I think nullptr is the correct way to go. NULL is just unsafe.
Entity->PrintType would be a static method in Java, and you can call static methods on a null reference.
This explaination was soo clear, thank you!
Null is a pointer to address 0, which is usually invalid for anything that isn't the kernel.
i thought the thumbnail was a jab at Kanye
great explanation! thanks for the video!
12:33 Pretty much summerises the coders life in 2 seconds.
I like how the thumbnail used black, whose RGBA would also be 00000000 - same as a nullptr. 🤔
Also dropped in to say congrats on 500k subscribers!
Hi Cherno!
It's amazing how much depth there is in the humble zero!
Would you consider making a video on variadic templates or custom allocators?
It usually isn't zero, it's more likely to be:0xFFFFF...
As many F's as there are in a memory address...
I really like c++ series on this channel
2:04 Regarding why it's considered poor form to explicitly write 0 or (void *)0 for NULL/nullptr, the word "portability" rings in my head like an obnoxious bell.
If hearsay serves me well, the actual memory address for null is (strictly speaking) implementation defined: I.E. You might find some funky machines, whose null addresses are somewhere other than 0.
Always love these videos!!! Thanks for making another one
I'm always surprised how helpfull C++ and C code is when thinking about assembler and reverse engineering. Thank you | good video :)
Wow, this was awesome! Thanks!
Absolute legend mate! Thanks
As a C# dev approaching to C++, this video blows my mind 😮
"I mean we like writing our code in english don't we"
Bro null is GERMAN
This Word also exists in english and a few other languages
I like how he explained the class with struct, like class functions are free floating functions with that entity* as the parameter, like this in Java, that's why cpp is more efficient when it comes to memory management
Java is memory inefficient because of:
* EVERYTHING is allocated on the heap
* Your code runs in JVM that runs natively. So, in a way, your code runs twice
Most of things mentioned above are mitigated by using some smart tricks in every new version of Java. So modern Java is not that slow but still slower than C++ in most cases.
@@igorthelight Yes, they are trying to implement python features in their updates. Is there any specific reason behind this memory thing in Java? So my teacher said that, Java is programmer friendly so it takes care of memory allocations by itself that's why unlike cpp we can't play with memory related stuffs in Java, is there any other specific reason for this?
@@Its.all.goodman I don't know another reason for that. Probably, it's just easier for everything being on the heap for JVM.
C#, for example, have proper stack allocation and a heap allocation. But it doesn't have a "true" VM. It's "CLR" is what it uses instead of a VM - it's faster but not as cross platform by default as JVM.
My opinion - if you need a more C++ like language - C# is better that Java in that case (it has GOTO, pointer operations and native integers which are faster). Java is more cross platform tho ;-)
So that's why noone could say that some language is the best xD
@@igorthelight Thank you for the information.