The ONLY C keyword with no C++ equivalent

  Рет қаралды 275,170

mCoding

mCoding

Күн бұрын

Пікірлер
@n0ame1u1
@n0ame1u1 3 жыл бұрын
Yaaaaaay, another C keyword that's important for micro-optimizations that I have to remember
@lukasjetu9776
@lukasjetu9776 Жыл бұрын
lmao
@akulkis
@akulkis Жыл бұрын
Or just don't use it and you don't have to worry about whether you are using it properly or not.
@norielgames4765
@norielgames4765 Жыл бұрын
You don't need to remember its name. You just need to remember that a certain magical keyword exists for when you need extra speed in a program with a lot of pointer arithmetic and no overlaps between the pointers. When you need it, just Google it.
@KleptomaniacJames
@KleptomaniacJames Жыл бұрын
Well, that optimization does not seem very micro to me
@LambOfDemyelination
@LambOfDemyelination Жыл бұрын
it's a safety feature too
@frans.8906
@frans.8906 3 жыл бұрын
Really enjoyed the video. I always found everything related to compiler optimizations very interesting. After seeing and understanding this, now I know why LLVM can occasionally optimize Rust code a little bit more than C code, it's because the "restrict" idea is baked into the rust borrow checker! Thanks for the video!
@mCoding
@mCoding 3 жыл бұрын
Very cool property of rust!
@1vader
@1vader 3 жыл бұрын
Although actually, this is still disabled in most cases because LLVM has/had lots of bugs related to this stuff because it's so rarely used in C and C++. Though all the bugs found so far have been fixed now so maybe this time around it will finally make it into the next stable Rust release, if we're lucky and they won't find another misscompilation in beta again like the last three times.
3 жыл бұрын
@@1vader yeah, maybe that's also a good reason to avoid restrict in C until those things get ironed out.
@9SMTM6
@9SMTM6 3 жыл бұрын
Yeah, although in fairness, programmers don't really think about this result. Since only the & mut is guaranteed to be exclusive, I'm not sure what results that will have. I mean all the situations explained here should still always work with Rust, but I'm not certain if we missed something. Another thing where Rust is able to gain speed, btw, is because of its move semantics and/or call conventions.
3 жыл бұрын
@@9SMTM6 not sure I understand. The issue with Rust is there are so many &mut llvm screws up. Or better said, it's issue with LLVM. Of course the proper fix is just fix those bugs but we need to have something working in the meantime.
@oj0024
@oj0024 3 жыл бұрын
It would be cool if you cover the details of C's inline (inline/extern inline/static inline) vs C++'s inline.
@venkateshhariharan4341
@venkateshhariharan4341 3 жыл бұрын
yes, that's a great video idea
@oj0024
@oj0024 3 жыл бұрын
What do you want to know? Are you asking why this would be an interesting topic?
@mCoding
@mCoding 3 жыл бұрын
Now that's a really technical topic! We'll see, added it to my list of ideas 💡
@darckangenoir
@darckangenoir 3 жыл бұрын
Would love to hear what he has to say :) But for now, there is a great video about inline in the C++ weekly series from Jason Turner: kzbin.info/www/bejne/fZ3Hd6eOj9Caj9E
@TranscendentBen
@TranscendentBen 3 жыл бұрын
@@mCoding And I thought restrict was Really Technical!
@arthur1112132
@arthur1112132 Жыл бұрын
10:05 memmove actually doesn't need any temporary buffer. It works the exact same way as memcpy, except it checks the pointer overlap by comparing the addresses and reverses the copy order (copies from end to start) if the destination is located after the source in memory. This ensures the data it overwrites is either unsignificant -outside of the source range) or has already been moved.
@erikkonstas
@erikkonstas 11 ай бұрын
I think there's also the nitpick that it can't use SIMD instructions in some cases; consider this memory chunk: 0x10 - 0x15: 00 01 02 03 04 05 We want to copy 5 bytes from 0x11 to 0x10, therefore we expect the following result: 0x10 - 0x15: 01 02 03 04 05 05 However, with (4-byte) SIMD, the first shift would result in this: 0x10 - 0x15: 00 02 03 04 05 05 There is one remaining byte to copy, from 0x11 to 0x10: 0x10 - 0x15: *02* 02 03 04 05 05 Whoops!!! A solution could be to also use a SIMD read, but... that would simply mean accessing some memory locations more times than necessary.
@arthur1112132
@arthur1112132 11 ай бұрын
@@erikkonstas SIMD are not necessary here since ther's no computation to apply to the bytes. It's a simple copy, so just using a wider data type (registry) is enough. (I don't know how the compiler would optimize this, but using SIMD seems overkill since a normal registry can perform this task just as well). Basically, the single fact of reversing the copy order depending on the "direction" of the overlap is enough to ensure we get the expected result. In your example, we want to copy from 0x11 (source) to 0x10 (dest). Since the dest is "before" than the source, we just copy normally from left to right, which, starting with the same base memory chunk, gives something like this : 0x10 - 0x15: 00 01 02 03 04 05 First, since we want to copy 5 bytes, we can copy 4 at once with an unsigned 32 bits integer. We do so from 0x11 to 0x10 , which give this result: 0x10 - 0x15: 01 02 03 04 04 05 Then, since ther's only one byte left to copy, we can just use an 8 bits integer copy from 0x15 to 0x14: 0x10 - 0x15: 01 02 03 04 05 05 Now, if we were to copy from 0x10 to 0x13, we would have to do the same in reverse (copy from right to left), because destination (0x13) is biger than source (0x10) this time.
@SvetlinTotev
@SvetlinTotev 3 жыл бұрын
I'm just as interested in your C/C++ videos as I am in your python and algorithm videos. You are great at picking interesting and useful topics and condensing them in a short video.
@mCoding
@mCoding 3 жыл бұрын
I appreciate the kind words very much! Thanks for your support!
@nathanoy_
@nathanoy_ 3 жыл бұрын
Yes. His toppic choices are amazing!
@StephenHoldaway
@StephenHoldaway 3 жыл бұрын
Thank you! The official docs on restrict are pretty dense and never simply state what it promises to the compiler like you have here so succinctly 👏
@mCoding
@mCoding 3 жыл бұрын
Glad it helped!
@psauchelli65
@psauchelli65 3 жыл бұрын
I dont know squat about C or C++, but some detailed insight about how compilers approach stuff like this and ways to think about code optimization is useful!
@mCoding
@mCoding 3 жыл бұрын
Even if it doesn't make sense or seem relevant now, one day it could just *click*. Happens to me all the time. Ohh yeah that thing from 10 years ago I totally get it now.
@jppittman6067
@jppittman6067 3 жыл бұрын
I love this. There are some many beginner programming videos out there. It’s nice to be able to watch something that helps me improve, even as a working professional.
@mCoding
@mCoding 3 жыл бұрын
That's my goal, something that even experienced professionals can enjoy! (Not something I achieve in every video, my viewers are very knowledgeable already)
@Liam3851
@Liam3851 3 жыл бұрын
@@mCoding 17 year professional here (Python/Scala/Java/C++), love the videos. I only wish you'd been doing something like the Python 3.10 preview videos (which were excellent) for C++ back when C++11/14 were coming out-- I hardly recognize the language anymore.
@MichaelGrantPhD
@MichaelGrantPhD 3 жыл бұрын
Very interesting! I passed it along to our Numba lead because he necessarily immerses himself in compiler intricacies.
@mCoding
@mCoding 3 жыл бұрын
There are currently 0 uses of the restrict keyword in numba, an opportunity for more speed perhaps? Though I'm not sure if numba is bottlenecked anywhere that this would help. Nonetheless thanks for sharing my video!
@MichaelGrantPhD
@MichaelGrantPhD 3 жыл бұрын
@@mCoding on that I'm not surprised. I don't think Numba itself is likely to be sped up by its use. But the specific issues around aliasing, overlapping memory, etc. that the restrict keyword deals with is something I know he spends a lot of time thinking about!
@xavierandradev
@xavierandradev Жыл бұрын
Aliasing is the main reason Fortran has historically been faster than C/C++. In Fortran aliasing is forbidden, it is illegal to pass the same argument twice to a function or overlapping regions of an array.
@ADVscout
@ADVscout 3 жыл бұрын
Any interesting 'quirk' about languages and compilers is a great topic
@frigzy3748
@frigzy3748 3 жыл бұрын
I've never heard of restrict keyword during 15+ years of writing C code daily. Thanks!
@mCoding
@mCoding 3 жыл бұрын
Happy to help! Glad to have an experienced C programmer in the audience to keep me honest!
@atrus3823
@atrus3823 3 жыл бұрын
Enjoying the switch to C/C++ lately. That's kind of my focus for learning right now, so it's timely.
@nadavgolden
@nadavgolden 3 жыл бұрын
I didn’t know restrict was even a thing! You captured my attention nicely with the mysterious title, then proceeded with a very captivating technical explanation of what restrict is. I loved it! Video-production note for you: I would suggest having less noticeable cuts between sentences. I don’t know what your setup is, but maybe a teleprompter would help?
@mCoding
@mCoding 3 жыл бұрын
My sentences are so short because I'm speaking spontaneously, I don't have a script. I could probably up my production quality by making a script ahead of time and using a teleprompter to get longer shots 😅. Thx for the tip I will look into teleprompters.
@firstname4337
@firstname4337 3 жыл бұрын
@@mCoding your videos are fine
@priyanshu_hiro
@priyanshu_hiro 3 жыл бұрын
Today morning I was reading getline function there was restrict keyword used in parameter list. Searched it online was able to somewhat make sense out it. Your video very much cleared the useage. Thanks.
@mCoding
@mCoding 3 жыл бұрын
Perfect timing for me! Glad it helped!
@samyaks
@samyaks 3 жыл бұрын
This was a good one, your explanation was good and easy to follow too. I was intrigued by restrict ever since I noticed it in some of the string.h function declarations. I would definitely like to see more content around compiler optimizations, C/C++ weirdness (or features) and maybe assembly too!
@mCoding
@mCoding 3 жыл бұрын
Great to hear! I love C and C++ as much as Python so if my viewers do too there will be more of all of them!
@juliankandlhofer7553
@juliankandlhofer7553 3 жыл бұрын
Benchmark, Benchmark, Benchmark!!! As you said at the end, in most cases you don't really need this keyword. It only makes sense when you have benchmarked your code and made sure that you would really benefit from the added mental overhead of using functions with restrict parameters. Really interesting as always!
@mCoding
@mCoding 3 жыл бұрын
Totally I should have emphasized this more in the video!
@tacokoneko
@tacokoneko 3 жыл бұрын
in Rust aliasing mutable pointers is illegal and the compiler prevents it so when LLVM is more stable the Rust compiler will apply noalias optimizations to all pointers by default so that is very cool
@sebastianramadan8393
@sebastianramadan8393 3 жыл бұрын
Don't benchmark; profile. Benchmarking software seems to be related to hardware; profilers are what we use to measure the performance of software. The distinction may seem negligible on a high level, but there's this problem with people writing their own erroneous "benchmark" code, whereas they ought to save time using a profiler instead, and come to a correct conclusion (rather than an incorrect conclusion) as a result.
@juliankandlhofer7553
@juliankandlhofer7553 3 жыл бұрын
@@sebastianramadan8393 well, kinda. Both have their place. Benchmarks are certainly easier to reproduce and therefore will give you a solid A-B comparison. But it is easy to write an irellevant benchmark if you dont set it up like in production. Its also easy to just randomly slap useless optimizations everywhere by *just* profiling I'd say: Profile first to find bottlenecks -> try building a *reproducable* benchmark around those bottoenecks -> optimize -> benchmark again -> profile in production. Obviously, it depends on what you're doing and the complexity of your products, but that would be my approach.
@td19xyz
@td19xyz 3 жыл бұрын
@@tacokoneko You're thinking of mutable references. Raw pointers exist in rust, and are allowed to alias memory
@ExCyberino
@ExCyberino 3 жыл бұрын
I love these more technical videos !!! Thank you
@mCoding
@mCoding 3 жыл бұрын
You're welcome! Thanks for watching!
@N....
@N.... 3 жыл бұрын
Actually, C++ does have an analog for C's restrict keyword. When you make the parameters different types, the compiler uses the same behavior as if the restrict keyword was used. This is why you might see "strong type aliases" used in some cases, since they can be a negative-cost abstraction.
@mCoding
@mCoding 3 жыл бұрын
Hmmmmmmmm. I'm not sure if I consider the strict aliasing rule (which is what allows strong type aliases to enjoy restrict-like optimizations) to be equivalent to restrict since sometimes the types really should all be the same, or allowed to alias like void* or char*. But I did consider talking about it in this video so I guess they are closely related...
@forchtsengar6071
@forchtsengar6071 3 жыл бұрын
@@mCoding I guess the point of @Nicholas Bradon was that C++ with its capabilities of generic user-defined types allows you to enable the same compiler optimizations. For example you can make a source and a sink type as strong types which even convert into each other. But since they are actually different types as parameters, they don't alias and thus enable the same optimizations as the restrict keyword.
@ABaumstumpf
@ABaumstumpf Жыл бұрын
For this we first would need actual strong type aliases - which the Committee has also always opposed -.-
@styleisaweapon
@styleisaweapon Жыл бұрын
the hilarious thing is that VB6 had the Assume No Aliasing compiler flag.
@ChrisWijtmans
@ChrisWijtmans Жыл бұрын
Actually you should avoid using pointers at all in C++. There are smart pointers for a reason.
@ABaumstumpf
@ABaumstumpf Жыл бұрын
it is one of the things the committee for whatever reason just fails to accept: Restrict is a very useful keyword. If they have problem defining what it would mean in relation to a "this" pointer - then just say it is not allowed or make it undefined behaviour - as they have done with tones of new features. It would also be less of a problem if they would not have block every single suggestion for strong type aliases: Often you have multiple parameters that are conceptually different types but fundamentally just integers. Say matrix-indices. If you could give them actual strong types then not only would it give rise to the strong aliasing rules and thus directly act like "restrict" does, it also would prevent a whole butload of bugs that happen due to mixing up parameter order. I had to deal with a function taking in 5 int-pointers for arrays for some simple statistics.... the genius who wrote that called them "param1" to "param5" ... have fun figuring out that the first and last are used as in-out-parameters while the other 3 are strictly for reading data.
@gabiold
@gabiold 3 жыл бұрын
Regarding memove and temporary buffer: You can check at the begining where the areas overlap. It the dest starts at higher address than src then you could reverse the loop, not needing temporary buffer.
@jmc7656
@jmc7656 3 жыл бұрын
It’s very rare that i consider a KZbin coding channel to actually be presenting any sort of correct or useful information. This channel is one of those rare cases
@mCoding
@mCoding 3 жыл бұрын
I am honored and thank you for the kind words!
@johnshaw6702
@johnshaw6702 Жыл бұрын
Definitely worth making. I haven't looked at the C standard in years and I see that I should. Years ago I was someone who spent a lot of time answering questions about both the C and C++ standards. But I see they've made more changes than I expected.
@potato9832
@potato9832 11 ай бұрын
I am interested in picking up C development again. The C17 and C23 additions are interesting. I enjoyed writing C code back in the day, but the majority of the industry moved on forcing me to adapt. I miss writing code for the machine rather than writing code for the abstractions. Somewhere things went off the rails with layering abstractions on top of abstractions, and we've forgotten that we're writing software for real world machines with real world limitations.
@johnshaw6702
@johnshaw6702 11 ай бұрын
@@potato9832 It definitely had its upside. I worry that today, that us old school are few and far between. The upside of that is that people that actually know how things work are in demand. The majority don't actually understand how stuff works, because they don't have to.
@tpahere8756
@tpahere8756 3 жыл бұрын
I really enjoy that type of technical content, thanks a lot! I hope I'll be seeing more such content from you :)
@unusedTV
@unusedTV 3 жыл бұрын
Although I mostly subscribed for the Python intricacies, other technical videos are still interesting.
@mCoding
@mCoding 3 жыл бұрын
Good because I can't help myself 😀
@mohammedjawahri5726
@mohammedjawahri5726 3 жыл бұрын
I loooove this level of detail. Keep it up dude
@mCoding
@mCoding 3 жыл бұрын
Thanks a ton!
@Speykious
@Speykious 3 жыл бұрын
I love this kind of technical videos.the things we lack on this KZbin space. :D
@anashashim
@anashashim Жыл бұрын
At the 10:34 minute ... "But there was a lot of push_back." Tell me its pun intended.
@_nikeee
@_nikeee 3 жыл бұрын
In C++, unique_ptr might go in a similar direction, while not allowing pointer arithmetic etc. But it's a way to enfoce via the compiler to disallow aliasing to a pointer.
@mCoding
@mCoding 3 жыл бұрын
Actually, unique_ptr does not come with semantics of disallowing aliasing. unique_ptr is about ensuring there is a unique *owner* of the object, i.e. the unique_ptr is uniquely in charge of deleting the object. It is fine and very common to have many non-owning raw pointers pointing to what a unique_ptr owns. As such, the compiler cannot assume a unique_pointer's underlying pointer is not aliased.
@_nikeee
@_nikeee 3 жыл бұрын
@@mCoding well yes, I assumed that one does not mix it with raw pointers. But I don't know whether the compiler uses unique_ptr for optimization purposes. Probably not, for the reasons you mention.
@Maurycy5
@Maurycy5 3 жыл бұрын
As I do almost exclusively competitive programming ("almost" because I also have university assignments), I never knew about this detail. I never had to use the 'restrict' keyword. This reminds me, that in fact, I never had to use many, many keywords. So here are a few questions, perhaps ideas for future videos: What the heck is extern? What does static actually mean? Is it meant to mean something along the lines of "global for this function / structure / class" or is it about being inaccessible by code from other files? What does volatile mean? What are the differences between structs and classes in C++? (I know there are several, but honestly I have no idea if they're interesting enough for a video) What are the different stages of creating an executable from source code? (Preprocessing, compiling, linking, and possibly a couple others which I have never heard about) What are the other questions I wanted to ask which I do not remember right now? Man, so many questions... Loved the video! Cheers!
@stewartzayat7526
@stewartzayat7526 3 жыл бұрын
I'm not an expert, but maybe I can roughly answer a few of those questions. What is extern? To answer this, we must first differentiate between declaration of a variable/function and definition of a variable/function. Declaration introduces a name and type of the variable in some scope and tells the relevant parts of code that the variable exists somewhere in memory. Definition actually specifies where the variable/function is defined and/or what value it has: void foo(); // declaration void foo(){} // definition Consider this global variable: int bar; This syntax declares the "bar" variable with type int and also defines it as a global variable, i.e. it lives globally in memory. But what if you actually didn't want to define "bar", just declare it? That's exactly what the extern keyword is used for: extern int bar; This declares "bar" of type int, but it doesn't define where it lives yet. That means you can't actually use it, if you try to set it or use its value, the compiler will complain that "bar" is declared, but not defined anywhere. The advantage here is that you can declare the same name multiple times in different modules, and then define it in one module and all the modules will refer to the same variable when they use it. It's the same concept as declaring functions in a .h file to include the same function in multiple modules. If you don't define the function, you also get a complaint from the compiler (or linker, I should say). Difference between class and struct? There is almost none. The only difference is that members of struct are public by default and members of class are private by default. It also conveys some semantic difference to a human reading your code, but to the compiler, they are the same thing. What does volatile mean? Volatile tells the compiler that it can't assume anything about the value of the variable declared as volatile. Consider: int i = 0; while (i==0); The compiler can notice that i doesn't change and so the while loop is infinite, i.e. it optimises out the i==0 check and just loops indefinitely. volatile int i = 0; while (i==0); i is declared as volatile, so the compiler can't assume anything about its value, so the check i==0 will not he optimised out, in case somebody changes the value of i from outside the loop. This keyword is commonly used in multithreaded programming, or also with memory mapped I/O. What does static mean? To my knowledge, static can mean different things based on the context where it is used in C. Function or global variable defined as static is considered local to the compilation unit, i.e. if you declare an extern int bar in unit A and define a static int bar in unit B, then bar in unit A is still undefined because bar in unit B is local to unit B. Similarly for a function. If you define a variable static inside a function, then that variable is understood to live globally, i.e. not on the stack of the function. This means that when the function is executed multiple times, the value of the static variable is retained, unlike a value of stack defined variables.
@Maurycy5
@Maurycy5 3 жыл бұрын
@@stewartzayat7526 Thanks a ton for the replies! Especially thanks for sharing knowledge about extern. That being said, I still have this feeling that struct and class are different from each other in several, very minute ways besides the default member visibility.
@stewartzayat7526
@stewartzayat7526 3 жыл бұрын
@@Maurycy5 I guess I forgot to mention that inheriting from struct uses public inheritance by default and inheriting from class uses private inheritance by default, besides that, however, there is no difference. There is a geeks for geeks article describing some other differences, but they are saying straight up plain nonsense there.
@technologicalwaste7612
@technologicalwaste7612 3 жыл бұрын
TL;DR of Stewart's great effort post above: extern - The function or value is defined in another object file. static - The function or value cannot be used to define an extern declaration in another object file. volatile - The compiler must never assume the value bound to this identifier. Maybe you have never worked on a project with multiple object files. This is where multiple source documents are compiled each using `gcc -c objN.c -o objN.o', and finally linked using `gcc obj0.o obj1.o obj2.o main.o -o binary_exec', where binary_exec is the executable run by the user. The linker will attempt to resolve definitions for any undefined identifiers declared with extern by looking in the other object files present on the command line. You might wonder what a reserved word like `__extern_always_inline' could mean. This tells the linker to attempt to inline the specified function where it is referenced using an extern declaration. This is part of a process called link-time optimisation (LTO).
@rockpadstudios
@rockpadstudios Жыл бұрын
wow - I've been using C for 35 years and never noticed or used this. I've don't think I've ever seen this in code reviews either and I've worked in many different industries. Thanks for this. One of the things I wish I did more was to look at the assembly generated.
@Asto508
@Asto508 Жыл бұрын
Probably a good thing considering how easy it is to break code as soon as you enable -O3.
@meowzerus
@meowzerus 3 жыл бұрын
The restrict keyword (specifically noalias) is a little bugged right now in LLVM and GCC and may emit unsound code even when used correctly. Additional test cases from the Rust project exposed some deficiencies in the original implementation
@anlumo1
@anlumo1 Жыл бұрын
That has been fixed since this comment was written!
@meowzerus
@meowzerus Жыл бұрын
@@anlumo1 God I hope so, I've seen a few "this time it's fixed" posts and then something else comes up x.x
@anlumo1
@anlumo1 Жыл бұрын
@@meowzerus yeah, it was "fixed" multiple times, but I haven't heard anything about it in a while, so either people stopped looking too closely or it really works now.
@50PullUps
@50PullUps Жыл бұрын
I appreciate the gigantic text, which is unlike all other programming presentations where the host is unaware that an audience can’t read 12-point font on a 4K screen.
@davidkatz1017
@davidkatz1017 3 жыл бұрын
I always wondered about `__restrict` you see in C standard library declarations (as seen when writing c++). Very informative. Also all the godbolting is very appreciated, thank you.
@dexio85
@dexio85 Жыл бұрын
I love the acknowledgment of the real world applications :) In many videos like this over YT those presenters act as if there's only the "pure standard" and the land of "undefined behavior" while in practice, when you are an actual paid programmer that ships products you know you need to bend the rules often.
@jsalsman
@jsalsman Жыл бұрын
I've never seen it in production code. It takes a fair amount of thought to apply correctly inside inner loops where it might help.
@user-lv6qm3fj2z
@user-lv6qm3fj2z 3 жыл бұрын
0:00 - ok, this sounds like not just a welcome message, but more like "Hell, bit*hes, who said I only make Python videos? You wanna low programming! I'll give you low programming! you thought making stuff in pure C was the end? Prepare your sorry arses to some assembly!"
@mkt4941
@mkt4941 3 жыл бұрын
k
@bloody_albatross
@bloody_albatross Жыл бұрын
Side note: In Rust everything is restrict (I guess except unsafe pointers used for interfacing with C/ffi). Meaning you simply can't pass a reference to the same thing as mutable and immutable (or even as mutable twice) at the same time to a function. So in theory Rust can always apply those optimizations, but I know that in the past there where problems with LLVM that prevented Rust from enabling this. Meaning Rust is the first time this optimization feature of LLVM was used to that extreme extend and thus uncovered compiler bugs (miscompilations). I don't know what the current state of this is, if LLVM has fixed all the issues and it was re-enabled in Rust. I know there was a back and forth for some time where Rust enabled it, found bugs in LLVM and disabled it again until LLVM had fixed it and repeat.
@samuelallanviolin752
@samuelallanviolin752 Жыл бұрын
Fair enough although there are other places where safety tradeoffs are made in Rust for example in array bounds checking. I think with both of these things the micro-optimization is not significant enough to outweigh other factors (and if you did need that level of performance you would be checking the output assembly anyway to ensure everything is as good as it can possibly be). EDIT: Nevermind, the vector_add example has convinced me this is probably more significant. Would be interested to know if any of these would stop working in the presence of bounds checking (probably not)
@bloody_albatross
@bloody_albatross Жыл бұрын
@@samuelallanviolin752 If you can do the stuff via iterators instead of array index you don't have a bound check (only the implicit loop condition). And even with bound checks branch prediction helps. But yes, it is a thing where it can reduce performance.
@HaouasLeDocteur
@HaouasLeDocteur 3 жыл бұрын
I love this channel. More C/C++ content for sure!
@mCoding
@mCoding 3 жыл бұрын
Thanks! Will do!
@codahighland
@codahighland Жыл бұрын
Useful knowledge! I knew what restrict did, and I knew it wasn't in C++, but I didn't know about the extensions.
@vinterbjork4128
@vinterbjork4128 3 жыл бұрын
Stumbeled upon this video, and I must say I really enjoy this proper programming video in the sea of framework and loose concept videos that are out there.
@mCoding
@mCoding 3 жыл бұрын
Thanks for the kind words, glad you enjoyed!
@semicharmedkindofguy3088
@semicharmedkindofguy3088 Жыл бұрын
Crazy how I googled about this keyword earlier today at my work computer and now youtube recommends this to me on my personal phone.
@azratosh
@azratosh 3 жыл бұрын
Excellent video as always. As a long term viewer I can safely say that you never disappoint. Keep up the good work, man!
@mCoding
@mCoding 3 жыл бұрын
Much appreciated! Glad to have you!
@amirh6712
@amirh6712 3 жыл бұрын
I really love your C/C++ tutorials. Can you make some guides about C++ debugging and development systems? There are not a lot of tutorials out there that cover topics such as debugger attachment or, for example, how to develop and debug a dynamic library that is being used by an already build or compiled program
@Sparkette
@Sparkette 3 жыл бұрын
To add to what you said about having two versions of the function, one with restrict and one without: if the function is particularly complex, you might want to put the body in a separate file and #include it inside both functions, so you don't have to keep track of two copies of the same code. Or you can use a macro I guess, but it might look ugly having to put a \ after every line.
@mCoding
@mCoding 3 жыл бұрын
Possibly, yeah. That's a tradeoff you could choose to make depending on if it makes sense for your codebase.
@wrathofainz
@wrathofainz Жыл бұрын
Things being modular like that makes my brain feel good :3
@metal571
@metal571 3 жыл бұрын
Strong Jason Turner vibes in this video, I like.
@mCoding
@mCoding 3 жыл бұрын
He is a big inspiration for the channel!
@trapfethen
@trapfethen Жыл бұрын
The only thing I would change is make the overlapping function the default. Make the restricted function the longer named "opt in" function. That will help make sure future maintainers don't shoot themselves in the foot.
@v0xl
@v0xl Жыл бұрын
btw rust always provides the same pointer aliasing guarantees as restrict, as there can't be more than one mutable reference, and you can't have any immutable ones while you have a mut one. so for example you can't pass add_sub(&x, &y, &mut x) which allows the compiler to safely and automatically apply these optimisations. this is one of the guarantees that makes rust sometimes, but very rarely, outperform C in benchmarks. Of course when compared with proper optimized C code (with these guarantees specified explicitly, e.g. the restrict keyword and friends) it's more or less equal or *slower.* (slower: mostly due to additional checks Rust does, for example array bounds checking, which is included with all array accesses by default, unless the value is guaranteed to fall into array's size (this behavior can be changed using unsafe code))
@about2mount
@about2mount 10 ай бұрын
It's still there in C++. Its hidden inside several Libs in fact. Its also inside a BitLib that IBM developed and is called UNDERSCORE + restrict + UNDERSCORE and does the exact same thing with pointers being assigned.
@gblargg
@gblargg Жыл бұрын
9:12 Add an assertion to the non-overlapping version to catch misuse.
@bookle5829
@bookle5829 Жыл бұрын
I have now acquired the knowledge of restrict usage in C and (lack thereof) in C++.
@expiredlamb2000
@expiredlamb2000 3 жыл бұрын
The closest I have come to working with c++ is some 40 line arduino code, but I believe learning about this will be beneficial in the future none the less.
@mikicerise6250
@mikicerise6250 3 жыл бұрын
Awesome! Finally I understand what the man is going on about with all the "overlapping is undefined" stuff for memcpy! :D
@ryansamarakoon8268
@ryansamarakoon8268 Жыл бұрын
This is great! Please do more of these videos, you're really good at explaining these more technical topics 👀
@gblargg
@gblargg Жыл бұрын
10:58 You can always code the functions needing restrict in C and call from C++. Totally standard. If you want to use __restrict and variants, use a macro like MY_RESTRICT so you can make it appropriate for the compiler (including being nothing if it doesn't support it).
@viliml2763
@viliml2763 Жыл бұрын
Not if you need to use some C++ features in the functions
@JustSomeRandomIdiot
@JustSomeRandomIdiot 3 жыл бұрын
I don't even code in C and I found this fascinating, thanks.
@tobb10001
@tobb10001 3 жыл бұрын
Nice video as always. However, I would've enjoyed a side by side view with the Assembly with and without usage of the restrict keyword to find out which instructions are actually changing (or disappearing).
@mCoding
@mCoding 3 жыл бұрын
Fair enough, I kinda expected people interested enough to plug it into compiler explorer for themselves :). I definitely considered doing the side-by-side at one point but I don't recall why I decided against it.
@Florianmunz
@Florianmunz Жыл бұрын
Holy shit, I had a bug about using memcpy with overlapping memory. And now you just explain this. Was so hard to find this
@georgesanderson918
@georgesanderson918 3 жыл бұрын
Really enjoyed this video, we need more C/C++ videos!
@mCoding
@mCoding 3 жыл бұрын
More to come!
@rafagd
@rafagd 3 жыл бұрын
Ah, yes. The age old C/C++ tradition of offloading compiler responsabilities to the programmer.
@nyanpasu64
@nyanpasu64 3 жыл бұрын
At least now we have Rust which has a largely-sound compile-time check that it's impossible to alias mutable pointers, and forces the programmer to opt in using loud type-level syntax into aliased mutability, to help compilers and programmers to reason about code.
@gondoravalon7540
@gondoravalon7540 Жыл бұрын
0:40 TIL _Generic is a thing in C. Hmm, am I correct (from a few moments of Googling) in guessing this allows you to create the equivalent of template functions... or... maybe not EQUIVALENT, but a close enough analog?
@DiThi
@DiThi 3 жыл бұрын
You can always add a macro to use __restrict only where it's supported, and it's defined as nothing when it's not.
@maxaafbackname5562
@maxaafbackname5562 Жыл бұрын
Perfectly examples of why the "const" does not mean constant, but read-only!
@deanvangreunen6457
@deanvangreunen6457 10 ай бұрын
It may not have an analog, but it does have an opposite in c++, the volatile keyword, says that a pointer can be alter at any time from anywhere.
@mCoding
@mCoding 10 ай бұрын
True!
@cainabel2553
@cainabel2553 7 ай бұрын
The semantics of restrict are notoriously hard to define. But then, so are the semantics of pointers in a low level language, of unions (not sum types), etc.
@titfortat4405
@titfortat4405 Жыл бұрын
This strongly reminds me of mutable references in Rust. In fact, I think a * restrict T is almost exactly like a &mut T in Rust. Which explains why there are so many potential dangers with restricted pointers.
@Amipotsophspond
@Amipotsophspond 3 жыл бұрын
you should do a video on using the compiler, building, and make files. like deep meaning of all the flags and stuff. it seems their are a lot of tutorials on how to program in C++ but few on setting up, using, and modifying big make files. so to new people its kind of feels like RTFM but when I type in man g++ Manual assumes a lot of knowledge, the manuals are sometimes confusing, non existent, or maybe I am just not finding the manual for the job. but you explain things well so you should go threw compiling and make files.
@MrJpocreva
@MrJpocreva Жыл бұрын
Great video. Well worth it from end to end. Keep it up.
@TheHamoodz
@TheHamoodz 3 жыл бұрын
Really helpful, I've always wondered what restrict really was!
@john.dough.
@john.dough. 3 жыл бұрын
12:00 - I would totally be interested in C + C++ content!
@rmt3589
@rmt3589 Жыл бұрын
Where can I find that chart that shows C & C++ equivalents?
@atrus3823
@atrus3823 3 жыл бұрын
Request: would you please consider doing a video on all the different value types in C++ (i.e., glvalue, rvalue, lvalue, xvalue, and prvalue)? That is the thing I find the most confusing.
@mCoding
@mCoding 3 жыл бұрын
Got it! I've added value categories to my list of topics, that's one that I'm sure many C++ programmers struggle with.
@atrus3823
@atrus3823 3 жыл бұрын
@@mCoding awesome! Thanks so much. Can't wait.
@Armageddon2k
@Armageddon2k Жыл бұрын
I havent written a single line of C in all my years as a programmer, but its still interesting to see how and why it does what it does.
@chaimlukasmaier335
@chaimlukasmaier335 3 жыл бұрын
Great Video, I had never heard of your channel, but your explanation was great and understandable!
@tommygrandefors9691
@tommygrandefors9691 Жыл бұрын
You are the son I never had. 😊 I didn’t think people kept track of those things. Good. 👍
@thecprogrammer3908
@thecprogrammer3908 2 жыл бұрын
Nice video. Although it would've made sense to point out the example functions probably would have been inlined, with the compiler heuristic seeing that the values don't overlap even if the restrict qualifier isn't given.
@TranscendentBen
@TranscendentBen 3 жыл бұрын
I know a good bit about C (I was learning it just before the ANSI K&R came out), so I was surprised I hadn't heard of restrict before. I HAD heard of this "pointer problem" and how the compiler has to do bla bla bla, and how it makes C not as fast as FORTRAN, which I found disappointing for a "modern" language. Now all I have to know about restrict is whether it works with the compilers I use ...
@zofe
@zofe Жыл бұрын
It means that even Non-'volatile' qualified variables are actually still considered somewhat volatile to start with, unless it is promised by 'restrict'.
@farhan-momin
@farhan-momin Жыл бұрын
Your explanations are really good
@zrodger2296
@zrodger2296 3 жыл бұрын
I did not know about this at all, so I learned something. New to your channel. Anytime you want to do a C video that'd be fine with me!
@Godigentil97
@Godigentil97 3 жыл бұрын
Great video, I had no idea restrict was a thing. Very good explanation :)
@morthim
@morthim 3 жыл бұрын
if you take questions, why would a compiler use keywords like that to tokenize intent, instead of making the compile take a little bit longer to create the tokens from nothing during the compile step? if you are using a compile time language, then you are transforming set code to assembly. so why create a word to make the optimization, instead of running the AST to look for features or patterns of operations before generating? taking this to another level, is there an obvious reason that a compiler doesn't SIMD as much as it can during compile?
@mCoding
@mCoding 3 жыл бұрын
The short answer is that if the compiler can prove that, e.g., the value of *amount has not changed from line to line then it will do the same optimization and delete the extra read. You could see this if you added a main to the compiler explorer link and called the add_sub function and return the value of *x from main. You will see that the whole thing disappears and the compiler just returns a constant from main without ever calling any function at runtime. However, due to things like the halting problem, the compiler often cannot determine properties of the code even when they are true. That's where the programmer can step in with things like restrict. You tell the compiler "don't worry about it, I promise, feel free to do any extra optimizations". We also saw in the fib example that it might be incorrect to allow these extra optimizations, and only the programmer who knows the intent of the function can make the decision. As for SIMD the compiler does generally try to use SIMD instructions as much as possible.
@morthim
@morthim 3 жыл бұрын
@@mCoding thanks for the response. that was really interesting
@gabiold
@gabiold 3 жыл бұрын
This cannot be checked compile-time! In some simple cases it might, but when pointers are dynamically allocated, come back from library function whose code might not known by the compiler, it cannot determine if it could optimize this or not. It could check it at runtime, but this is exactly an optimization hint to make the run time faster by telling the compiler to exclude these checks that you know will never be true anyway.
@LukeAvedon
@LukeAvedon Жыл бұрын
"Nice shooting, son. What's your name?" "Murphy."
@perfectionbox
@perfectionbox 3 жыл бұрын
could a c++ dev move critical functions into a .c module and use C compilation for them, thus gaining use of 'restrict' in a c++ project?
@mCoding
@mCoding 3 жыл бұрын
Yes, this would be similar to just using a C library. However, as I mention at the end, you may be able to use restrict in C++ directly using a language extension from your compiler.
@aisawaloki1571
@aisawaloki1571 Жыл бұрын
if I said a piece of memory is not referenced by any other pointers, the main reason is I assume the value should not be modified elsewhere, or at least I don't want so, thus as an alternative way to achieve the outcome of restrict keyword, i would instead copy those values to a local variables at very first. the nowadays compiler optimization should smart enough to handle it. is it right?
@robertbrummayer4908
@robertbrummayer4908 3 жыл бұрын
Excellent and interesting video, James. So pedentically speaking, C++ is not a superset of C :D
@Vaaaaadim
@Vaaaaadim 3 жыл бұрын
I knew that C++ was not a strict superset of C but not how so, good to know one way in which they're different now :P
@sebastianramadan8393
@sebastianramadan8393 3 жыл бұрын
#define fubar(x) _Generic(x, default: (char*[]){"hello", "is there anybody out there?", "not if you can hear me", [sizeof x]="is there anyone home?"} fubar('a') struct relax { size_t information; char hurts[]; }; There's also something subtly different about the scope of nested declarations. If I recall correctly, in C, the declaration for `struct bar` is hoisted outside of `struct foo`: struct foo { struct bar { int x; } x; int y; } ... so that you can use `struct bar` elsewhere. C++ has some strange clause that renders a recursive `main` entry point undefined... Eh, there's still quite a few differences. char *blatant_cpp_error = malloc(0); // write C like this; don't cast to facilitate for C++ or you're enjoying the worst of both worlds
@halfsourlizard9319
@halfsourlizard9319 Жыл бұрын
Just imagine the optimisations you could do if you eliminated mutation entirely.
@aDifferentJT
@aDifferentJT Жыл бұрын
The other thing you can sometimes do is use strong typing in C++ to get this same effect under the strong aliasing rule
@ABaumstumpf
@ABaumstumpf Жыл бұрын
but C++ does not allow fro strong type aliases so for most cases you would be forced to write a lot of boilerplate and hope that the compiler can optimise it all away - just cause some people dislike having a single new very functional keyword.
@Almeida19001
@Almeida19001 2 жыл бұрын
Most cpp compilers support __restrict__ statement eventhough its not in the standard. Also c++ cuda supports restrict
@hupa1a
@hupa1a 3 жыл бұрын
This is really high quality content, thank you!
@protudorin
@protudorin 3 жыл бұрын
Thanks for the vid pal, I appreciate your work
@PvblivsAelivs
@PvblivsAelivs 3 жыл бұрын
Okay, I just checked _The C Programming Language_ by K & R and there is no mention of that keyword. auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while Those are the keywords. The book makes note that some implementations include "fortran" and "asm." "It doesn't make sense to have a restrict int." It doesn't make sense to have a restrict anything. This is one of those "a camel is a horse as designed by committee" type of things.
@mCoding
@mCoding 3 жыл бұрын
K&R 2nd edition was published in 1988, but restrict was added into C in c99, so it is no wonder your book is incomplete. Though K&R was the defacto standard for C in the early days before there even was a C standard, it is silly to try to use it today to argue against the literal standards document that defines what C is.
@PvblivsAelivs
@PvblivsAelivs 3 жыл бұрын
@@mCoding K & R is the proper standard. What we have is a case of a committee inserting a large amount of useless garbage to a language that required no updating in an effort to justify its own existence. It is my contention that the K & R book is not incomplete. It is a proper standard. A language like C should remain simple. It should not be subjected to perpetual updates so that people can't keep up. And it is reasonable to define a "line in the sand" such that no further updates are recognized. If you want to convince me that it is "silly" to argue against the "standards document," you need to be able to tell me their aren't going to be any more of them. You see, I see standardization as useful. But it needs to be once and done. Perpetual updates mean that it is not really a standard.
@mCoding
@mCoding 3 жыл бұрын
I am confused why you make a comment about the restrict keyword not being part of C when in reality your viewpoint is that c99 isn't C. A comment explaining why you believe that e.g. c89 or K&R C is the best version of C would be a welcome view to hear about. Saying that c99 isn't C is silly.
@PvblivsAelivs
@PvblivsAelivs 3 жыл бұрын
​@@mCoding It is not a useful part of C. It doesn't belong. It is the result of committees trying to justify their existence. I am not convinced anything useful has been added since the publication of the K & R book. And so I still consider it the proper standard.
@muhammadrahimi1547
@muhammadrahimi1547 3 жыл бұрын
@@PvblivsAelivs not useful ? Restrict is the reason C can be as fast as Fortran
@thawne4235
@thawne4235 3 жыл бұрын
Thanks, learnt something new today. Not something I was seeking for, but someday perhaps it might come in handy...
@obinator9065
@obinator9065 Ай бұрын
Every major C++ compiler supports it. So I defined it via a macro.
@andrewbuckley2627
@andrewbuckley2627 3 жыл бұрын
The only keyword that scares me, let's me create bugs I'm not smart enough to find.
@davidgillies620
@davidgillies620 Жыл бұрын
Using restrict in things like memcpy exposes it to serious speedups like DMA and kernel-level memory mapping (copy on write).
@comradepeter87
@comradepeter87 3 жыл бұрын
I see a lot of people in the comments talking about Rust. Could you do a video on it and what makes it so special? (I'm sure you find the language redundant as you could probably catch all the memory issues better than the borrow-checker, but it's a lucrative language for all others!)
@atimholt
@atimholt Жыл бұрын
I wonder if C++20's range stuff allows the same kinds of compiler optimizations.
@pedrogabrielnogueira1068
@pedrogabrielnogueira1068 2 жыл бұрын
Now ik why a lot of the standard library functions had that restrict keyword... Cool video. Me more grow smart
C++ Sudoku Solver in 7 minutes using Recursive Backtracking
6:57
Return Value Optimization and Copy Elision in C++
9:54
mCoding
Рет қаралды 40 М.
Сестра обхитрила!
00:17
Victoria Portfolio
Рет қаралды 958 М.
Леон киллер и Оля Полякова 😹
00:42
Канал Смеха
Рет қаралды 4,7 МЛН
Cursed C++ Casts
17:41
Logan Smith
Рет қаралды 75 М.
Faster than Rust and C++: the PERFECT hash table
33:52
strager
Рет қаралды 611 М.
the cleanest feature in C that you've probably never heard of
8:13
C++ cache locality and branch predictability
10:43
mCoding
Рет қаралды 86 М.
Stop using std::vector wrong
23:14
The Cherno
Рет қаралды 159 М.
Emulating a CPU in C++ (6502)
52:28
Dave Poo
Рет қаралды 1 МЛН
Advanced C: The UB and optimizations that trick good programmers.
1:12:34
Eskil Steenberg
Рет қаралды 178 М.
31 nooby C++ habits you need to ditch
16:18
mCoding
Рет қаралды 841 М.
The Most Useless Keyword in C?
10:26
Jacob Sorber
Рет қаралды 69 М.
Сестра обхитрила!
00:17
Victoria Portfolio
Рет қаралды 958 М.