Тёмный
No video :(

The Most Useless Keyword in C? 

Jacob Sorber
Подписаться 162 тыс.
Просмотров 69 тыс.
50% 1

Опубликовано:

 

21 авг 2024

Поделиться:

Ссылка:

Скачать:

Готовим ссылку...

Добавить в:

Мой плейлист
Посмотреть позже
Комментарии : 604   
@georgecop9538
@georgecop9538 2 года назад
Extern is good when making a program with multiple languages(Assembly and C). You have a function in assembly and you want to use it in the c code. Edit: Wow, thanks for this many likes, didn't expect that
@leokiller123able
@leokiller123able 2 года назад
It's good to make nice global variables too (you declare it as extern in the header and initialize it in the source )
@warnaoh
@warnaoh 2 года назад
@@leokiller123able yeah it was really nice when recoding malloc.
@R.B.
@R.B. 2 года назад
For interop, I'd argue it is very necessary. You won't use it for Hello, World!, but for a code base with mixed languages it's how you bridge them.
@berylliosis5250
@berylliosis5250 2 года назад
Function declarations are implicitly extern though, so it doesn't help in that case. It's only ever useful for global variables
@leonmoto1931
@leonmoto1931 2 года назад
Exactly it's very useful for microprocessor programming
@jakobpederpettersen2179
@jakobpederpettersen2179 2 года назад
The "extern" keyword is necessary when you need to access a global variable defined in a different translational unit. You rarely need this feature since having global variables is considered an anti-pattern in the first place. However, there are a few cases where you cannot avoid it: I once worked on a simple hobbyist operating system written in C. The keyboard buffer was updated by an interrupt rutine whenever a key was pressed and released. In order for other parts of the operating system to read which keys were pressed, I had to refer to the keyboard buffer and the number of keystrokes in the buffer, as a "extern" variables.
@pierreabbat6157
@pierreabbat6157 2 года назад
I use "extern" in header files for exactly this.
@alvinabad7636
@alvinabad7636 2 года назад
Exactly this.
@blooddude
@blooddude 2 года назад
Yup, exactly! It’s a low level language feature. And many of us use C for its low level features!!
@SerBallister
@SerBallister 2 года назад
@@pierreabbat6157 "I use "extern" in header files for exactly this." Imagine not using extern in your header files.. :D
@urbex9797
@urbex9797 Год назад
// With/without extern communicates different intent: int forwardDeclaration; extern int externDeclaration; // Also, to declare an item without storage space (type void), you need extern: extern void end; // ok void end; // error // Example: const void etext, edata, end; int is_mem_static(const void * c) { return c < &end; } void if_heap_free(void * m) { if (0 == is_mem_static(m)) { free(m); } }
@DeviRuto
@DeviRuto 2 года назад
Extern is essential in a lot of cases. Many source-to-source compilers depend on autogenerated global variables, and the only way to access a global variable defined in a different object file is by declaring it as extern.
@dblitroot
@dblitroot 2 года назад
"register" keyword is important (especially on microcontrollers) for doing very low level stuff when you must not mess up the stack and want to avoid assembly. Like working on task schedulers.
@tremon3688
@tremon3688 2 года назад
That was exactly what I was about to point
@EnkoVlog
@EnkoVlog 2 года назад
"register" just recomendation for compiler, there is no 100% garanty that your variable will be located in the register...
@tremon3688
@tremon3688 2 года назад
@@EnkoVlog I think it depends on which compiler you are using
@TranscendentBen
@TranscendentBen 2 года назад
And if something is compiler dependent, that's a problem. Compilers were "stupid" 20+ or 25+ years ago, and the "suggestion" keywords register and inline were "helpers" for the compiler, but now compilers are as smart as the best assembly programmers, because the compiler writers know how to put that knowledge into compilers (also, computers are bigger and faster, and can run much more complex compilers). Modern compilers are better off ignoring these keywords. See Matt Godbolt's videos on his Compiler Explorer to see what modern compilers do, it'll blow your mind!
@EnkoVlog
@EnkoVlog 2 года назад
@Eddie Amaya, using =! working. Could you please give a piece of ASM code generated by C with "register" to confirm that really works on FreeRtos/micrium ?
@leokiller123able
@leokiller123able 2 года назад
The auto keyword is useless in C because it's implicit so specifying it doesn't change anything
@MH-ri2fb
@MH-ri2fb 2 года назад
And ironically, auto is extremely useFUL in C++ (but of course has totally different meaning).
@w01dnick
@w01dnick 2 года назад
@@MH-ri2fb It had same meaning but was deprecated for a long time then removed and replaced with new meaning.
@alvinabad7636
@alvinabad7636 2 года назад
You need the extern keyword on a variable to tell it that you are declaring it and not defining it, and that the actual definition is in some other file. You can get away with it by omitting the extern keyword but it will be confusing since it may read as being defined, and without any assignment the reader will assume it is initialized to zero. The compiler will catch it anyway if you defined the variable more than once. But that's a rather painful reminder. When that happens, you usually just add the keyword to remind you that it is just declared and that the actual definition is somewhere else.
@user-zb2bl2jc5x
@user-zb2bl2jc5x 8 месяцев назад
Something like "Multiple definitions" will be thrown if one tries to omit the extern keyword with variables, because the compiler will try to define it implicitly. To avoid it we need to put "extern" anyway. Or am I wrong? In case of variables extern is essential because it separates declaration from definition, by default the compiler does the both and it leads to linkage problems.
@ssl3546
@ssl3546 7 месяцев назад
@@user-zb2bl2jc5x you're right and there are a whole lot of ignoramuses making videos and commenting on videos. i had to stop when he said that. K&R's book is probably the shortest language definition you'll find and he hasn't even read that. pathetic.
@ajtan2607
@ajtan2607 2 года назад
So here's a bit of a summary about the keyword `auto` prior to C23: ---------- What is the use of `auto` in C? ---------- `auto` explicitly specifies that a variable declared at block scope shall have an automatic storage duration. This means that the storage is AUTOmatically allocated when entering the block where the variable was declared and is AUTOmatically deallocated when exiting from the block (by reaching the end or by a `return`, `break` or `goto` statement). A variable declared inside a function (local variable) has an automatic storage duration by default. ---------- Why is `auto` not commonly used in C? ---------- Variables with automatic storage duration only exist inside a function. Since local variables have automatic storage duration by default, `auto` serves little to no purpose at all. int x; is basically the same as auto int x; given that `x` is a function-local variable. ---------- Why did `auto` exist in the first place? ---------- `auto` is historical. It is a remnant of C's predecessor, the B language. It existed for backwards compatibility with B code. ---------- Is there any reason to use `auto` in a modern C code? ---------- Practically, there is none. This keyword is probably only used by those who are very pedantic and want to clearly (and unnecessarily) state that their variables have an automatic storage duration. ---------- What does `auto` do in C++? ---------- C++ `auto` used to work the same way as in C, until C++11, where it was given a new meaning. Since C++11, it is now used for automatic type deduction. It can be used to specify the type of a variable or the return type of a function based on the return type of an expression (sometimes in combination with `decltype`). `auto` type deduction does not make anything dynamically typed. It is done at compile-time. Once the type is deduced, it cannot be changed. ---------- What does `auto` do in C23? ---------- Starting from C23, `auto` can now be used for automatic type deduction of variables, similar to C++11 `auto`. ---------- B Language: www.bell-labs.com/usr/dmr/www/kbman.html C auto: en.cppreference.com/w/c/keyword/auto C++ auto: en.cppreference.com/w/cpp/keyword/auto
@austindolan3142
@austindolan3142 8 месяцев назад
Very useful comment
@niggacockball7995
@niggacockball7995 8 месяцев назад
Thanks
@realdragon
@realdragon 8 месяцев назад
That's actually cool, I like there's backward compatibility even if it's something from 400 years ago
@sanderbos4243
@sanderbos4243 2 года назад
I'm pretty new to C, but I was reading up today on how the "inline" keyword can tank performance if the function doesn't fit in the L1 cache, so how it's better to just leave it up to the compiler to inline functions when it wants to.
@peppigue
@peppigue 2 года назад
Compiler developers are really really really smart people
@MH-ri2fb
@MH-ri2fb 2 года назад
This is true, but inline is also just a suggestion to the compiler (unless you use "__attribute__((always_inline))"). If the optimizer heuristics deems it suboptimal, it will ignore you, the coder, completely :)
@sanderbos4243
@sanderbos4243 2 года назад
@@MH-ri2fb I see, thanks!
@oreo6392
@oreo6392 2 года назад
@@sanderbos4243 To further elaborate, the compiler won't automatically inline functions in a different translation unit unless you are using lto (iirc, correct me if I am wrong). When you inline in C you can either use static inline, just inline. With static inline, the compiler will see if the function should be inlined, in which case it would be inlined. If it cannot, then the compiler uses a static declaration of that function instead. With just an inline it's the same except the compiler uses a external declaration of the function (in which case you have to define the non-inline version of the function seperately). In general, you should just use static inline.
@StefanoTrevisani
@StefanoTrevisani 2 года назад
I use inline mostly to avoid having to create an implementation file for simple functions: hust define them in the header and mark them as inline, no linking problem and you're done.
@embeddedbastler6406
@embeddedbastler6406 2 года назад
That's why I like that Rust does not use types like int or float. Instead you type i32, u64, u8, i128, f32, f64. Also, there is usize/isize for getting the most efficient indexing type for your platform.
@MH-ri2fb
@MH-ri2fb 2 года назад
For C it's good practice nowadays to use stdint fixed width types for integers, so you can get similar guarantees. size_t may or may not be optimized per architecture like usize. (disclaimer: I also love Rust, these are just lessons I've taken and applied to C).
@SpeedingFlare
@SpeedingFlare 2 года назад
I heard that, historically, int is meant to be assigned the most efficient integer size of the platform it's being compiled for. Which is why in a "for" loop from 0 to 9, I allow myself to use int and not uint8_t, especially if "i" is getting cast in the loop anyways
@adammucci3463
@adammucci3463 2 года назад
@@SpeedingFlare In that case, why not use uintfast?
@SpeedingFlare
@SpeedingFlare 2 года назад
@@adammucci3463 interesting, I've never heard of that. I'll have to check that out!
@inkryption3386
@inkryption3386 2 года назад
I don't think it's necessarily the "most efficient indexing type", whatever that means, I'm pretty sure it's just a pointer sized integer.
@ocrap7
@ocrap7 2 года назад
The register key word can be used with the inline asm keyword to specify a specific register for the variable (register int foo asm("eax") = 5;). This might be useful in systems programming.
@Hauketal
@Hauketal 2 года назад
Correct observation. But this is system specific and no longer C.
@jlewwis1995
@jlewwis1995 2 года назад
Can you define multiple different versions is the variable for different architectures like an arm foo and x64 foo or do you have to pick one and stick with it
@ocrap7
@ocrap7 2 года назад
@@jlewwis1995 I mean you can't do it directly but you can use preprocessor ifdefs to test __x86_64__ or __arm__ to compile a variable declaration with arm registers or a variable declaration with x64 registers but these are compiler specific and probably not the best to use. Up to you.
@xcoder1122
@xcoder1122 7 месяцев назад
Register is a hint keyword and just because the five major compilers today usually ignore it doesn't mean that any C compiler on earth will for sure ignore it. The C standard does not force the compiler to put anything into a register just because you use register, the same way it won't force a compile to inline a function just because you use inline. But it's untrue that this keyword never has an effect in major compilers. E.g. there are three situations where GCC will generate different code when you use the register keyword: - When used as part of the register variable extension. - When -O0 is in use, the compiler allocates distinct stack memory for all variables that do not have the register storage-class specifier; if register is specified, the variable may have a shorter lifespan than the code would indicate and may never be placed in memory. - On some rare x86 targets, setjmp doesn’t save the registers in all circumstances. In those cases, GCC doesn’t allocate any variables in registers unless they are marked register. So this keyword does have an effect even in GCC and it may have a larger effect in other compilers depending on certain situations.
@moritzmolle6609
@moritzmolle6609 6 месяцев назад
It'd've been a good idea to separate hints from stuff that's "linguistically" necessary, like "extern", from the beginning. Many compilers use double underscore-stuff for that, anyway.
@michaelkotthaus7120
@michaelkotthaus7120 2 года назад
Thank you for this quite interesting episode. Beyond 'auto' and 'register', I like to mention the unary plus-operator. Though it is no keyword, you can write some wierd expressions like +5 *+ + +9 which is actually 45.
@mdxggxek1909
@mdxggxek1909 2 года назад
It's not useless, it's meant to impress your friends
@RyanLynch1
@RyanLynch1 2 года назад
what the heck even
@adam051838
@adam051838 2 года назад
Could you state the order of precedence here for this lowly noob?
@arcturuslight_
@arcturuslight_ 2 года назад
@@adam051838 it's like unary minus that negates a number, but the plus doesn't negate it, so "+4" is the same as "4". In the example it's just 5*9=45. It may do some stuff that would've happened if a variable was to be used in any numerical expression, like update the type or give type error, but is generally useless.
@dascandy
@dascandy 2 года назад
Unary plus serves as a universal "decay the type of this expression". `+[]{return 42; };` will be a function pointer.
@m4l490n
@m4l490n 2 года назад
I have never used int or unsigned int, I have always used int32_t or uint32_t, in fact, I don't feel comfortable when I see int in the code because that makes me stop and think for a second where the code is going to run. But if you use uint32_t then it will always be a 32 bit unsigned integer whether on an 8-bit micro or my 64bit Linux laptop.
@benhetland576
@benhetland576 2 года назад
It will always be 32 bit, but only if it compiles! It is not guaranteed to do so according to the standard, and there are platforms with word sizes not a multiple of 8 bits. Use a plain int if you don't want to consider where the code is going to run and you know you are in a smaller numeric domain anyway (say less than 10k), long if less than 2 million, or otherwise you can consider one of the least*_t or fast*_t types according to your needs to get the best choice on each platform.
@lazula
@lazula 2 года назад
@@benhetland576 While this is a fair point, odd word length architectures are very specialized. You will already know if you need to worry about this beforehand. More important imo is knowing that the exact (u)intN_t types are required to be that exact length and won't exist if it isn't possible, e.g. a CPU that only supports 32-bit words as variables can't have uint8_t, but it will have a 32-bit uint_least8_t. stdint is, well, standard, and you shouldn't be afraid to use it.
@benhetland576
@benhetland576 2 года назад
@@lazula Yes, I agree with you. The header is standard since C99, and the fact that something then doesn't compile should be a good indicator that something needs to be addressed specifically on that platform. Note that if one also needs support for an early C++ compiler (likely?) these types were not supported until several years later (2011?).
@sarahkatherine8458
@sarahkatherine8458 2 года назад
In one of my practice test in university, they gave me 80/100 even though I got all output correctly. Turned out they also evaluate the code by hand, and every of my uint32_t was marked as "not suitable". They wanted me to use 'unsigned'. Yes, not 'unsigned int', just a single 'unsigned' keyword.
@benhetland576
@benhetland576 2 года назад
@@sarahkatherine8458 The unsigned keyword doesn't really indicate a type in itself. Along with short and long these are _type modifiers_ for another base type, so unsigned alone is merely a shorthand for writing unsigned int, long a shorthand for long int, unsigned long for unsigned long int, etc. I suppose the "non-suitability" would have meant the potentially reduced portability of such a choice. A plain 'unsigned' vs the full 'unsigned int' is simply hyper-pedantry IMHO, and could be grounds for a formal complaint.
@donno2048
@donno2048 2 года назад
Unless you are willing to use __asm__ which is not very fun nor elegant you'll need to use `register` for some low-level programs where the stack itself must be preserved, but the most effective aspect of this keyword is that like a register should work you cannot access its memory address, so if you want to make sure that during the entire program no (unknown) change to the variable has taken place you could declare it as a register thus any call to it by address won't compile. And anyways the reason nothing changes in the compiler when adding the register keyword is that some compiler straight up ignores this flag. Again, in some cases the compiler will ignore this keyword, but it is still a powerful check for a call by address.
@smrtfasizmu6161
@smrtfasizmu6161 2 года назад
When I write __asm__ the compiler doesn't ignore that. Also, you can write machine code instruction as a char array and then cast that char array to a function and call that function. However, you will have to write machine code this way.
@0x007A
@0x007A 2 года назад
Some of those "useless" keywords are for systems-level programming and are still used today.
@makidoko
@makidoko 2 года назад
7:34 You weren't alive at this time... I was, and was C developer. And yes _register_ saved my life when I refactored an image format converter, resampling, with big/little endian switching, my project went from 10 minutes processing by document, to about less than one minute, using _register_ . You just have to use it efficiently, because defining every single one as a register will bring nothing, while using it on the right variables (in loops), will be stupendous. But I guess that today, with caches we don't really need it anymore if our code is well written.
@tktktktktk826
@tktktktktk826 2 года назад
I believe compilers also have gotten to the point where that will most likely be optimized for you, so the compiler will figure out whether something should be in a register or not.
@sbypasser819
@sbypasser819 2 года назад
YOU THINK YOU ARE BETTER THAN HIM???? OR ANY OF US JUST BECAUSE YOU WERE BORN EARLIER??? IDIOTS LIKE YOU ALL OVER THE PLACE SAYING "IN MY TIME...", NOBODY CARES THAT YOU WERE LUCKY TO LIVE THOSE MOMENTS WE WANT OUR MOMENTS TOO YOU KNOW!!
@Alche_mist
@Alche_mist 2 года назад
@@sbypasser819 No need to shout. This was just a bit of history lesson, not some "put down your teacher babble". On the other hand, you were just rambling with Caps Lock.
@petrustefanescu5842
@petrustefanescu5842 2 года назад
@@sbypasser819 Take a chill pill
@sbypasser819
@sbypasser819 2 года назад
@@Alche_mist its not history lesson, dont you know these people think EXACTLY that they put stg on the table because they were born earlier and we are stuck in this rotten modern world with android 11 if our old device dies
@georgecop9538
@georgecop9538 2 года назад
If someone is saying smthing about goto or register, remember that they are heavily used in the Unix world
@vercolit
@vercolit 2 года назад
Register used to be useful, but it's not really anymore
@DavidCourtney
@DavidCourtney 2 года назад
Interesting, I didn't even know auto existed to be honest.
@AnFunctionArray
@AnFunctionArray 2 года назад
Auto comes from B where there were no types and only auto/extern I suggest reading the C89 rationale and the bell labs reference manual if you are interested
@cmdlp4178
@cmdlp4178 2 года назад
What about signed? I have never ever seen it in use. Integers are signed by default. But also int might be useless, because you could write just signed instead. All others like unsigned long int would just be unsigned long etc...
@leduyquang753
@leduyquang753 2 года назад
char can be signed or unsigned.
@leduyquang753
@leduyquang753 2 года назад
@@Brock-Landers It's not, the implementation can make it either signed or unsigned.
@arti5musicc
@arti5musicc 2 года назад
@@Brock-Landers char isnt signed “by default”, it depends on the architecture.
@saulaxel
@saulaxel 2 года назад
@@leduyquang753 Right. here is the quote from the standard draft if anyone is interested: "The three types char, signed char, and unsigned char are collectively called the character types. The implementation shall define char to have the same range, representation, and behavior as either signed char or unsigned char"
@CircuitrinosOfficial
@CircuitrinosOfficial 2 года назад
Signed is useful if you need to cast an unsigned int to a signed int. I can't think of any other uses.
@Spiderboydk
@Spiderboydk 2 года назад
I've only watched until 1:29 and haven't seen the comments. My guess is the register keyword, because compilers have become so much better than they used to be, so I don't consider it that useful anymore. Edit: I didn't even know C had an auto keyword. TIL.
@LordHonkInc
@LordHonkInc 2 года назад
Hmm, I'd probably guess "signed" since I can't off the top of my head think of an instance where it isn't implied if omitted (I just checked, and according to reference at least since C11 there is always _a_ default implication; for integers it is always signed, for char it depends on the architecture but casting a char to unsigned char and back does, by definition, result in the original value). So yeah, I'd say signed is functionally obsolete bar the edge cases of weird cross-compiling.
@xcoder1122
@xcoder1122 7 месяцев назад
The point of long double is not to get 128 bits but to get "as much floating point precession as possible" and if your system only has double precision, then long double is the same as double, so you do not lose anything by using it, you still got maximum precession possible.
@zackyezek3760
@zackyezek3760 7 месяцев назад
“Register” was much more useful back in the days before x86, when 8-bit and 16-bit CPUs were for most computers & not just limited things like embedded microprocessors. I wasn’t there for it, but my dad and granddad were also systems programmers and used C when it was brand new. Apparently it was very useful in the days of K&R C when POSIX was also emerging as a cross platform systems API spec, and most machines had very limited RAM with potentially wildly varying instruction sets (e.g. all sorts of weird address sizes, etc.). Register was useful for keeping your stack size below a quite low hard cutoff, and for passing data between C and raw assembly (which you still often needed to write OS-specific or resource intensive code in those days). Back then every company making computers had its own hardware, OS, compilers, etc. so you couldn’t just assume that the tools would correctly figure out what variables should go in registers; early GCC might do it right without the keyword, but Solaris or Deck might not.
@xcoder1122
@xcoder1122 7 месяцев назад
"It's going to depend on the machine you are running on" is pretty much true for the majority of C code to begin with, as that's the whole point why C even exist, it's a slightly higher level cross-platform macro assembly language, that frees you from targeting a specific machine but as a compromise makes litte guarantees to be able to run on almost any machine. Also funny how you now start to worry about different behavior on different machine and just a few seconds before you said "my machine has 32 bits int and 32 bits longs then what's the point of having long instead of int" where you seem to not worry about other machines at all, since it only matters how your machine works.
@lsatenstein
@lsatenstein 2 года назад
I code a master source module that analyzes the command line parameters, and then the functions therein call functions residing in other source files. Extern serves a purpose. The GCC compiler does not like any variable to be used before being set, and it will complain if that happens (compiler flag for -Wall) . But, when the variable is set in one source and used in a second source, the compiler has to know to not complain. A complain message also sets up a returncode for the Make utility, which generally ceases to continue. Extern tells the compiler and also the linker, that it should not complain about "use before set", and also, to check for missing match. If the global variable is declared without extern, it is considered as locally global, to this source file only, By the way, I test my code with gcc and with clang, two excellent compilers.
@Muttisuri
@Muttisuri 2 года назад
The number thing I actually like how Rust does it, i8 i16 i32 i64 i128 for signed integers, u8, u16, u32, u64, u128 for unsigned integers.
@StopBuggingMeGoogleIHateYou
Fair enough about auto, long, and short. Extern is useful when you have a variable defined in a library. Your code needs to be able to refer to the name of the variable, but the variable itself won't be defined anywhere in your code. It also tells the linker about the linkage for that symbol.
@simontillson482
@simontillson482 7 месяцев назад
I was thinking the same, about extern in library code. Tlib won’t include any functions that are not defined as extern, either. So even if you had their function declarations in your library’s header file, they wouldn’t be able to be found by the linker unless they were declared as extern during library compilation. Not sure if that is still the case with modern compilers, but I think it must be… static libraries kind of depend on it.
@StopBuggingMeGoogleIHateYou
@StopBuggingMeGoogleIHateYou 7 месяцев назад
It was a good video other than that, but the comments about extern really missed the mark. Putting it first and saying that you'll never use it even if you code in C every day for your whole career. Hello? Using variables defined somewhere other than the current translation unit?
@adriangrana1239
@adriangrana1239 2 года назад
I personally think register is the most useless, I personally never used it and as far as I know the compiler will ultimately decide whether a value belongs in a register or not if I understand correctly.
@birenpatel7652
@birenpatel7652 2 года назад
If you think of the "register" keyword as actually meaning "addressless" then it becomes a lot more interesting and useful for modern applications. It allows the compiler to perform safety checks in your code much like "const" allows for.
@benhetland576
@benhetland576 2 года назад
@@birenpatel7652 That is actually one of the benefits of the keyword. You cannot take the address of such a variable, which may (on a rare occasion these days) help the compiler take that decision to dedicate a register for it.
@burningglory2373
@burningglory2373 2 года назад
Sometimes embedded system specific compilers treat register differently that does speed up operations.
@GRBtutorials
@GRBtutorials 2 года назад
0:47 Actually, you counted correctly, it’s just that “unsigned” is repeated.
@1e1001
@1e1001 2 года назад
extern: quite useful for importing code from other languages (wasm in particular comes to mind) long: honestly just group long, int, short, float, and double together, they're all unsized register: kinda useful if you have a microcontroller, but mostly useless auto: practically useless, it's literally the default behavior for variables
@TheVertical92
@TheVertical92 2 года назад
0:56 Must be 34 keywords then. Bcs you have unsigned two times in the list
@francomasella3543
@francomasella3543 2 года назад
There's a case not that rare that you may need to use extern (I needed in an exam and took some time to realize it). If you work with forks and events, you are mostly obliged to use some global variables to communicate between them. And if you use multiple files in a single program, then you must declare those variables as extern or otherwise there will be declared "twice". Imagine you have a main file, a functions one and a header file: you declare your global variables in the header as extern, and then include the header inside both your main file and your functions one. If extern is not used, the variables will be seen as twice declared and everything collapse.
@user-zb2bl2jc5x
@user-zb2bl2jc5x 8 месяцев назад
There is nothing wrong with a variable being declared twice, the problem appears when they are defined twice (multiple definitions error). Extern helps to avoid it
@FraggleH
@FraggleH 7 месяцев назад
As well as the 'global variable' usage, 'extern' is also used with inline functions when you need to take it's address for either: a) passing as a function pointer b) linking in the event that the compiler decides to *not* inline for some reason Pre-C23, 'auto' easily won the 'most-useless' keyword in ISO C as the only time it wasn't redundant, you could instead just write 'int' explicitly (a whole character less!) It was really only there to support some code written pre-standard. C23 adds the C++-style use though, which actually makes it quite useful now.
@dickheadrecs
@dickheadrecs Год назад
i love reading books with c code published in the 80s and early 90s. there’s a whole bunch of keywords in there i’ve never seen anywhere else
@dragonblade3166
@dragonblade3166 2 года назад
why are int and long not standardized and is it the same in c++
@leduyquang753
@leduyquang753 2 года назад
int is meant to be the most optimal integer type on the particular platform and yes it's the same in C++.
@IamTheHolypumpkin
@IamTheHolypumpkin 2 года назад
On microcontrollers I always use stdint, simply because I want to use as little FLASH and RAM as possible. On desktop for better or worse I stick with the regular short, int and longs.
@Hofer2304
@Hofer2304 2 года назад
The register keyword is not useless. Here is a short example: #include int main(void) { register const a = 23; int *b = &a; *b=42; printf("%d ", a); } This program does not compile, but if you remove the register keyword it does compile, the output is then 42 on my PC and 23 on Termux on Android.
@w01dnick
@w01dnick 2 года назад
I think you wanted to write `*b = 42;` and `%d`. But anyway that's an UB.
@BorlandC452
@BorlandC452 2 года назад
There's an old FAQ that I still goto when I need a refresher on C language constructs: c-faq (with the usual top-level domain suffix, which I can't type out because RU-vid will flag it as spam) Question 1.12 talks about the "auto" keyword.
@adamsfusion
@adamsfusion 2 года назад
As far as I'm aware, auto only exists _because_ of B, the language preceding C. In B, there's only 1 type, the computer word, or we'd just say "an int". You'd need to use auto in order to specify that the variable wasn't an extern (extrn). That's it, really. When C came around, it needed a much better system to represent this new PDP-11 character-thingie, so they decided to add types. Since, predominantly, variables are local, they decided to make "extern" the optional word and implicitly specify "auto". So why does C have "auto"? Because B had it. C compilers will, in fact, automatically assume the type as "int" (1 computer word) if you specify auto, but no type, just like B did.
@sameerplaynicals8790
@sameerplaynicals8790 Год назад
I agree that "auto" is useless but register should still be given some importance because one should always prepare for the worst compiler, one with almost no optimization. Your videos are great, by the way!
@georgerogers1166
@georgerogers1166 7 месяцев назад
Auto is nice in C++, should of used it in Java and C# over var.
@brianhginc.2140
@brianhginc.2140 7 месяцев назад
@0:45 - no, there are 34 keywords listed, not 35 as you wrote at the top right. You have 'unsigned' in your list twice, so the total count is 34.
@alerighi
@alerighi 7 месяцев назад
Extern is common as a keybaord. You use it every time you need to define a global varibale in an header file such that it can be accessed from other C files! I mean it's one of the most common keyword that I use...
@itsmaxim01
@itsmaxim01 7 месяцев назад
extern is useful in header files for declaring stuff that works both in c and cpp
@gokhangunay4345
@gokhangunay4345 2 года назад
If you want to directly interact with your machine such as reading a specific cpu register directly, "register" is indispensable. so yes it is not useful for those not dealing with low level but for core embedded guys it is quite useful.
@matthieusimon7836
@matthieusimon7836 2 года назад
How do you read cpu registers in C?
@gokhangunay4345
@gokhangunay4345 2 года назад
@@matthieusimon7836 For ARM architecture e.g. register uint32_t __regfpscr __ASM("fpscr"); can be used to read floating point status control register.
@momoanddudu
@momoanddudu 6 месяцев назад
Re integer type sizes * The types in stdint.h are not mandatory. * Only the relative sizes are dictated, that is sizeof(long) >= sizeof(int) >= sizeof(short) >= sizeof(char). * A char variable has CHAR_BIT bits in it. CHAR_BIT must be at least 8, but it might be larger. Re how many bits a long double has, its sizeof(long double) * CHAR_BIT. You can static assert on it having sufficient number of bits. Note that today processors might give you more than you've asked for, e.g. a C compiler might translate floats to 32 bit floats, then the processor would auto extend them internally to perform multiplications, division, etc, then shorten the result back at the end.
@kFY514
@kFY514 2 года назад
My take on those: extern is useful for writing 'extern "C"'. Yes, that's C++ and not C, but oftentimes you need to write C code that will stay valid in C++, and 'extern "C"' is necessary for that. stdint.h types are generally better than short, int or long, but... stdint.h defines them in terms of typedefs into, well, short, int and long. So these are necessary to implement the standard headers at least ;) There are also a ton of headers that declare short, int and long arguments and return values, and I'd argue that when you declare a variable with the intention of the variable to go in or out of such API, it's the best and most portable approach to just stick to the same declared type. Which will end up having a different size on different platforms, but that's the problem of the library you're calling, not with your code. register is sometimes useful when used together with compiler-specific extensions, to actually access a specific CPU register in low-level code, without using outright assembly. auto is completely useless.
@ItsCOMMANDer_
@ItsCOMMANDer_ 7 месяцев назад
Func fact, the one of the only instace where valid c code isnt valid cpp code (at least to my knowlage) is when the "restrict" keyword is used.
@kFY514
@kFY514 7 месяцев назад
@@ItsCOMMANDer_ Not true. Simple example: char *ptr = malloc(42); malloc() returns a void pointer. In C, that can be implicitly cast to any other pointer, in C++ that's a compile error. There are *a lot* more subtleties like that. Empty structs have a different size in C than in C++. Many C features appear in C++ very late, e.g. C99 designated initializers were only made legal C++ 20 years later (although things like that are widely supported as compiler extensions). It's not super hard to write C code that is also legal C++, there are even compiler options like -Wc++-compat in GCC that will alert you about many such subtleties. But they are there, and it's also pretty easy to stumble upon one of those.
@ItsCOMMANDer_
@ItsCOMMANDer_ 7 месяцев назад
@@kFY514 bruh, my cpp compiler (g++) only gives an warning
@suncrafterspielt9479
@suncrafterspielt9479 2 года назад
I do agree that the long keyword somehow is useless and obfuscates the code and portability a bit. However, the size of an int ist most of the time the size of a word on the given system. So when you want a for loop to run 200 times, an int would just increment and compare if it is above 200. However if you specify a 32 bit int on a 64 bit system, it would increment, clear the upper 32 bits and compare. The other way around if you explicitly specify a 64 bit integer on a 32bit system, it would add the overflow (which is always 0) to a second 32 bit variable. So what I am trying to say: When you need highly performant code and you need it to be portable with similar performance, you might be best off with using the normal int type.
@MH-xb3kp
@MH-xb3kp 2 года назад
The stdint.h header also has fast keywords, for example int_fast32_t which will provide the fastest signed integer type with a width of atleast 32 bits.
@suncrafterspielt9479
@suncrafterspielt9479 2 года назад
@@MH-xb3kp Ohh thanks, good to know. Didn't know that
@paulk314
@paulk314 2 года назад
Most useless: register, inline, auto Almost useless: signed (since ints are signed by default, but the signedness of char is implementation defined, so it's not entirely useless), while (since it's kind of a special case of the for loop) Oh, and you have unsigned in your list twice, which probably explains why you said "34" but then thought you miscounted :P
@marusdod3685
@marusdod3685 2 года назад
inline isn't useless at all. it allows you to declare functions in the header files and ship header only libraries
@paulk314
@paulk314 2 года назад
​@@marusdod3685 I was pretty sure that inline was just a compiler hint, and that static was used to specify that a function does not have external linkage, but it appears the answer is more complicated than this according to this Stack Overflow post: what-is-the-use-of-the-inline-keyword-in-c . In any case, I think you're probably still wrong. If you look at the STB repo (which contains header-only libraries), I think you'll see that the inline keyword is only used for C++.
@patryk_49
@patryk_49 2 года назад
@@paulk314 Inline keyword also reduces the size of binaries, because inline functions are not generated if they are not used.
@paulk314
@paulk314 2 года назад
@@patryk_49 the compiler decides whether to inline a function. The keyword just acts as a hint, not a requirement.
@ea_naseer
@ea_naseer 2 года назад
replace while with do...while. whenever I see someone use do...while I always ask them why? What are they thinking to use do...while?
@justwatching6118
@justwatching6118 2 года назад
Class I never use that in C 😂😂
@johnsmith1953x
@johnsmith1953x 7 месяцев назад
*For register keyword, you will see changes if you change the optimization level* of the compiler and whether avx or sse code is generated.
@xequals-pc1wl
@xequals-pc1wl 7 месяцев назад
@johnsmith1953x You mean "Controls to manual, captain, I'm taking over"
@brunoleite3958
@brunoleite3958 2 года назад
That was unexpectedly chaotic and I loved it
@nngnnadas
@nngnnadas 2 года назад
I might say register, maybe unless you work on embedded (especially since the compiler might ignore you).
@yolamontalvan9502
@yolamontalvan9502 7 месяцев назад
The only reserved word you mention is extern. I use it when I want to link C++ function to my C program. Is there another way that You know an I don’t know?
@xcoder1122
@xcoder1122 7 месяцев назад
The only true useless keyword in this video is "auto", all other keywords do have a meaning, even though register is rarely ever needed, but even in GCC there are three cases where different code is generated when you use register (see my other comment about that). Yet the video did not even explain why auto even exists in C, so let me help you out: The only reason why the keyword auto is found in C is for backward compatibility. Before there was C, there was a language named B. In B there were no variable types as int was the only variable type available but there was no int keyword to declare ints. Instead at the beginning of a function there were two declaration lists of variables used by the function (other than function parameters) and those were external ones ("extrn") and local ones ("auto"). So to declare two ints you'd write "auto a, b;". Does that syntax look familiar to you? Early C was supposed to be backward compatible to B as much as possible, making porting existing code as easy as possible, so C would require an auto keyword as well. And just as in B int was chosen as the default variable type in C, so instead of "int a;" you could write "auto a;" to declare an int variable. The inheritance of B is also why C used to assume an int return type, if no return type was given for a function. So the keyword was never intended to be use for new code written in C, only for B code converted to C. C also in introduced types, so variables could now be declared by starting with a type and that made auto superfluous, so it was declared that all variables declared by type are always "auto" unless something else is declared. And since old C code used that keyword and C wanted to remain backward compatibility with itself, the keyword was kept and never removed.
@ocrap7
@ocrap7 2 года назад
I think auto is the most useless as aren't all variables already "auto" by default?
@joshermar
@joshermar 2 года назад
"auto"
@raphaelmateusdasneves772
@raphaelmateusdasneves772 2 года назад
The register keyword is not as useless as it may seem. The functionality is used for two things. First of all, the fact that godbolt spits out register movement instead of RAM accesses is because the optimizer puts register there even if you don't. Without register being there in the first place, that wouldn't work. (Sure it can be done and is most likely being done not my stuffing the string in there but the functionality but the point stands) Secondly, it can be used for it's original purpose in low level computing libraries with long and complicated functions. It does make a difference when the function is complex enough that the optimizer may make mistakes, like multiple matrix multiplications for shading or similar. Sure splitting them in blocks makes it easier but the additional method calls and stack access does make a difference when something is run on a million verteces 144 times per second or more. Especially if it is older hardware that cannot profit as much from parallel computation on GPUs or if the task is another that cannot be done in parallel at all.
@CR3271
@CR3271 8 месяцев назад
Isn't extern required to avoid duplicate global variables? In the code base I work on we use extern regularly. I seem to remember leaving that word off one time and it resulted in a linker error complaining about duplicate symbols.
@HoloTheDrunk
@HoloTheDrunk 2 года назад
Ah, exactly what I need to make my code even """"smarter"""" and more confusing for my groupmates! On that note, I've personally never used the keyword `restrict`, though I don't do super low-level programming daily (we did do stuff like coding malloc and associated functions with all the corruption-proofing and optimisation though)
@Spiderboydk
@Spiderboydk 2 года назад
It's rare to use restrict, but in those rare cases it can make a huge difference in performance.
@BoundedByte
@BoundedByte 2 года назад
@@Spiderboydk absolutely. The key is that restrict helps with some aggressive compiler optimizations that are otherwise unsafe. I don’t find a lot of use for it on commodity CPU code but with specialized hardware (CUDA/C on GPU, for example) it can be night and day
@soniablanche5672
@soniablanche5672 6 месяцев назад
If you want to confuse them: int main() { static const _Atomic volatile unsigned long long int *const Hello_World = "Hello World!"; printf("%s",Hello_World); }
@durrcodurr
@durrcodurr 6 месяцев назад
extern: Most compilers assume that undefined functions that do have function prototype are already external. However, you cannot do this with global variables. If you declare a global variable in a header file, you need to mark it external explicitly. -- int/long/short: As you said, it's better to use the types declared in "stdint.h" to request specific types, unless you really don't care about the size. "long double" often translates to 80 bit IEEE floating-point as implemented in the FPU sections of Intel/AMD CPUs, but on other CPUs, it could be something different. -- "register" is _sometimes_ useful to trigger optimization when the compiler doesn't select a variable for optimization (which can happen if you have many local variables in the same function). Also, "auto" can be used to force the compiler to NOT select a variable for optimization. Again only relevant in functions that have many local variables. "volatile" on a local variable will similarly suppress optimizations (but it's mainly intended for global variables).
@dahalankur
@dahalankur 2 года назад
I can't believe you didn't talk about `inline` here!
@minneelyyyy
@minneelyyyy Год назад
extern is definitely not useless, although you can write function declarations without extern. the only real use is a global variable or global constant. long is definitely not useless as stdint is a new addition to C and cannot be used on some systems since it was added in C99 (so it will probably not exist in pre 1999 computers). It is a myth to say that this will make your code more "portable". auto seems to be more of a relic coming from b. maybe in very early inv development versions of C you had to use it? register can also be seen more often in old programs. These two "truly useless" keywords are really just relics from the past and exist for backwards compatibility. edit: saw another comment about how register is very much so important in microcontrollers, where paying attention to the stacks usage is important. as for long double, fair enough. but using it wont hurt your code! just because you cannot guarantee that the compiler will use higher precision floats doesn't mean its not worth using for the compilers that will. this video is honestly just kind of embarrassing. it ignores the rich history of C and just passes off all of these slightly-less-useful-as-time-passed features as "idk why that's there its useless." as well as ignoring everyone who is using C for a different purpose where these keywords are actually used and for good reason. i'm surprised you didnt bring up volatile.
@bogdanryabyshchuk4488
@bogdanryabyshchuk4488 2 года назад
It’s 34, not 35, after all. You have unsigned listed twice.
@vtreanor
@vtreanor 2 года назад
Too much idle chatter.
@darcyjane8515
@darcyjane8515 2 года назад
I despise "const". Don't tell me what I can and can't do! 😅
@giannimariani9744
@giannimariani9744 7 месяцев назад
You can't take the address of a register variable. It can be used to say, I don't want to alias this variable...
@angelcaru
@angelcaru Год назад
`restrict` and `goto` come to mind. Probably `restrict` because `goto` can be used for error handling and breaking out of multiple loops. `restrict` is so useless it didn't even make it into C++! EDIT && SPOILER ALERT: Wow! I didn't know about either of those! Still surprised you didn't mention `restrict`, but it's extremely useful when compared to `auto`!
@Keldor314
@Keldor314 7 месяцев назад
"restrict" can actually have significant influence on performance in some cases, which is why many C++ compilers have added "__restrict__" or "__restrict". Let's imagine that you have a function that is passed two pointers of the same type. In principle, the pointers could be pointing to the same piece of data, and to preserve correctness, the compiler needs to make sure to check whether they're the same, make sure any accesses get flushed out to memory, etc. This can get very expensive, especially if the pointers happen to be pointing to tree-like or graph-like data structures where aliasing could potentially occur at any node. Now, before you say "Ah! But compilers are good at optimizing!", consider what happens if these pointers are data-driven, pointing to data pulled in from a database, or maybe you're writing a library and these pointers hold parameters provided by some program using your code that hasn't even been written yet. That's right, the compiler often has absolutely no way of knowing whether the pointers could alias or not. But the programmer often knows. There are plenty of cases where the programmer can say "Yes, I know both parameters are float*'s, but one is an array of pressure values, and the other is temperatures. If they're aliasing, then something has gone very wrong somewhere else, so don't waste time checking and run my simulation faster."
@damir7780
@damir7780 2 года назад
to see the register in effect you can select for example compiler for Arduino, on that site you are using, (also a lot of MIPS and ARM compilers as well) and then you can see the difference in the produced assembly code
@haihonghuang
@haihonghuang 2 года назад
Some people say compilers doing smarter than programmers. The thing is, sometimes we don't want the compiler to optimize our code, specifically for safety related industry. For every piece of code that we wrote, it can be peer reviewed so we know how it really works, maybe not best in the performance, but it is safe. With compiler optimization, how do you known it always 100% correct? Some useful code maybe optimized out!
@benjaminshinar9509
@benjaminshinar9509 2 года назад
i can imagine a future in which c++ didn't exist and the C commitee decided to implement RAII with a special keyword 'heap', and then you'd have auto (local stack frame), static (always alive) and heap (RAII) as keywords. i feel as if auto was made to have something to contrast with 'static'.
@homelikebrick42
@homelikebrick42 2 года назад
the heap has nothing to do with RAII RAII is objects being constructed when they are declared and destroyed at the end of the scope RAIIs goal is to make sure that you can never have an object in an invalid state
@kebien6020
@kebien6020 2 года назад
Just to clarify, there *is* a couple of RAII types that deal with the heap, namely unique_ptr and shared_ptr. But RAII is for any kind of resources, like file handles, mutex, db connections or anything that has to be closed if you open it.
@joergsonnenberger6836
@joergsonnenberger6836 7 месяцев назад
@@kebien6020 There is nothing in unique_ptr or shared_ptr that forces the heap. You can pre-allocate the memory with alloca() or similar techniques and provide a null deleter.
@HansBezemer
@HansBezemer 7 месяцев назад
Here you got a great example of how you define a word. If I talk about "portability", I talk about the possibility to compile a program across a *WIDE* range of compilers - even legacy compilers like Turbo C or Coherent C (this one only supports K&R, really!!). No fancy *stdint.h* to be found here. The only way to get an idea of what a certain core datatype actually does is to make a program with a lot of *sizeof()* calls - or consult the documentation. So in my world *long* is not quite superfluous. What I tend to do though is make my own .h file with a lot of *typedef* where I can abstract certain datatypes like 32 bit signed, 16 bit unsigned, signed characters, etc. By matching certain compiler macros with certain definitions (e.g. *__TURBOC__* or *__GCC__* ) I can make the process somewhat transparent. Disadvantage: every time you add a new compiler you've got to update the thing. I agree with *auto* and *register* though. I've been programming C for about 40 years now and I *never* used them.
@xcoder1122
@xcoder1122 7 месяцев назад
"My machine has 32 bits ints and 32 bits longs" - so you are writing C code exclusively for your machine that never needs to run anywhere else? Interesting, as that's actually not what pretty much the rest of all programmers out there do most of the time. Sure, you can use the newer standard ints but keep in mind that exact width types are optional. The C standard does not require int32_t to even exist. It only requires int_least32_t and int_fast32_t to exist but those are not guaranteed to be 32 bit, only to be at least 32 bit. And guess what else is guaranteed to be at least 32 bit? long.
@peterg76yt
@peterg76yt 9 месяцев назад
'auto' is genuinely superfluous; the others may be unnecessary with some compilers or linkers but definitely required with others.
@xmoex6393
@xmoex6393 2 года назад
For me it's auto, register (never used them) and goto (just seems to be a bad idea to use even though I see it sometimes in the linux kernel, e.g. the TCP/IP implementation)
@Luxalpa
@Luxalpa 2 года назад
Goto is fine in a language that doesn't allow you to break out of nested loops.
@zachmanifold
@zachmanifold 2 года назад
i've only used goto twice ever. It's one of those keywords that mostly seems useless until you need it. As for the others, yeah, never used them myself either.
@ke9tv
@ke9tv 7 месяцев назад
'goto' is there for generated code. If you have a compiler for another language, and that compiler's target language is C, then it may need to use 'goto'. But in that case, the generated code is only for the C compiler, never for humans to read.
@user-lv6qm3fj2z
@user-lv6qm3fj2z 2 года назад
inline - even compiler ignores it :)
@jose6183
@jose6183 2 года назад
The only one I haven't really used is auto, and I think it should have had a similar functionality as in c++. The int,long, short types I agree though because for custom architectures and embedded systems, usually you use the types provided by their vendors' libraries. But you can use int for toy programs and experiments. All the others have specific cases where they are really useful, even necessary in some.
@Ribulose15diphosphat
@Ribulose15diphosphat 7 месяцев назад
I actually used 'auto' in a software-renderer: It consist of an outer-loop for the y-axis, inside a large switch-statement for different render-modes, and inside the cases inner loops for the x-axis. As the register-variables should be actually used inside the inner loops, but different modes may use different variables, it is best to declare all function-scope variables as auto to make sure the refister variables are reserved for the inner loop. Since the inner loop looks different for each mode, the register-variables must be declared inside a block.
@xijnin
@xijnin 7 месяцев назад
I hate "auto", with all of my existence
@saumyacow4435
@saumyacow4435 7 месяцев назад
And yeah, count me in with the dinosaurs. Once upon a time when I use to write C code for the Amiga, "register" did actually speed things up.
@GRBtutorials
@GRBtutorials 2 года назад
The most useless is… “if”, obviously. Who wants conditionals anyways?
@SianaGearz
@SianaGearz 6 месяцев назад
Before watching the video, "register" was my guess. Modern compiler families ignore the keyword entirely. Back in late 90s the Metrowerks compiler was actually super sensitive to it, avoiding the usage of most registers on RISC architectures unless you sprinkled some of this keyword. Even if there was full automatic register allocation, before SSA optimisations became common, it was often first come first serve so yeah that wasn't ideal.
@tomaszstanislawski457
@tomaszstanislawski457 Год назад
In C23 the `auto` is going to work the similar way as in C++. The type will be deduced automatically.
@AnonYmous-xp1ym
@AnonYmous-xp1ym 7 месяцев назад
You counted correctly in the voiceover, there are 34. Unsigned is listed twice.
@JamesJones-zt2yx
@JamesJones-zt2yx 7 месяцев назад
Yup. Nowadays, "register" just means "you can't take the address of this".
@bitskit3476
@bitskit3476 Год назад
@10:15 The auto keyword is mostly useless, with exception of the fact that it allows you to omit a type specifier. In C, everything is an int by default, so this is perfectly valid code: main(argc, argv) char *argv[]; { for (auto i = 0; i < argc; i++) puts(argv[i]); }
@vcv6560
@vcv6560 7 месяцев назад
I was thinking 'auto' from the start of the video. I've honestly never used it. Now 'register' was in my vocabulary from first using 'C in the mid 80s.
@playerguy2
@playerguy2 2 года назад
(written before watching the video) Only looking at the original 35, I'm calling it, in no particular order: "auto", "register", "signed", "volatile" "auto" used to have a use before becoming part of the standard where it basically became a synonim for "int", "register" should not have any impact on the assembly if the compiler is any good (i.e. optimizing compilers) or only does the bare minimum (in which case this feature should not be a priority), "volatile" is overused in general, but does have a use for low-level programming, "signed" showing up in your code is either redundant or a bug. (after watching) Isn't "extern" good for interfacing with pure assembly translation units? I'd love to use "uint64_t", but simply isn't avilable on the platforms I need C for. Yeah, you missed "signed".
@benhetland576
@benhetland576 2 года назад
'auto' wasn't needed before becoming "part of the standard" either. In those days you could just write nothing, and 'int' was the assumed type by default. The 'signed' is sometimes useful with 'char', but may also serve as explicit documentation/intent where a shortsighted programmer (aren't we all?) might otherwise be too tempted to change to an unsigned to quickly "extend" the useful numeric range and inadvertedly break the algorithm that depended on the signedness.
@SimonJentzschX7
@SimonJentzschX7 2 года назад
"volatile" is only important for embedded devs, because it tells the compiler to asume that this value may change for example by an interrupt and the compiler should not optimize for it.
@tremon3688
@tremon3688 2 года назад
@@SimonJentzschX7 and what about parallel programming?
@francomasella3543
@francomasella3543 2 года назад
Volatile is actually very useful if e.g. You rely on a single global variable to communicate two forks, you then cannot let the program assume its value, you must know everytime if one fork changed the value to the other. In general case, it's useful as long as you work on asynchronous implementations
@benhetland576
@benhetland576 2 года назад
@@francomasella3543 Generally what you need then is _Atomic, not volatile, but sometimes both.
@stevencolborne6845
@stevencolborne6845 7 месяцев назад
A common complaint about c, it is not portable from processor to others. It is unfortunately common to use local keywords to pretend portability.
@prototypemusic
@prototypemusic Год назад
auto for defining a local variable inside a function is pretty much useless (it's basically the opposite of static), but what if you used auto on a variable defined on global scope?
@JJSogaard
@JJSogaard 2 года назад
'Goto'. I just happy that I didn't grow up when BASIC was the first language you learned...
@eyesoars9212
@eyesoars9212 7 месяцев назад
Register is mostly useless now. It still has meaning a few places, but they are few and far between. In the far mists of C pre-history, the PDP-11 had 8 integer registers. One was used for the PC, one for the stack, and one for a frame pointer. The other five were for general use by the compiler, but... r0 was used for return values (ints), and r0 and r1 were used for return values (long). That left r2, r3, and r4 available for 'register variables', and the C compiler allocated them in r4, r3, r2 order. Generally, they were a hint that these variables were used a lot and, the PDP-11 having no cache to speak of, would result in smaller and faster code if the named variables were put in registers, rather than fetching them off the stack for each use. In these days, however, the poorest common compilers do a much better job of type checking, optimizing, and scheduling code than even the fanciest lint tools of yore. And so for 99+% of code, register is meaningless. (I will point out that the example used in this clip isn't a good one: even the compilers of yore would optimize a 'register' variable associated with r2-r4 to r0 if it was returned as soon as it was computed. So I wouldn't expect that example to have made a difference in compiler output even back in the days of the dinosaurs if optimization was enabled.) Long after the PDP-11, although partly as fallout from the PDP-11, the register keyword found significant use in the x86. In PDP-11 days, all floating point arithmetic was done in 'double' precision, and results stored to variables in whatever type the variable held. It was therefore helpful (numerically) if critical values, which might be 'float', were nonetheless held in registers, where they had type 'double', and used accordingly. This avoided loss of precision, and for things like dot products, could yield significantly better numerical results. The x86 had a similar issue: in the old days (pre-SSE2) the x86 FP "stack" model holds/held internal values with 80 bits of precision, but storing a value to a memory location truncates/truncated it to 64 (double) or 32 (float) bits (according to its type). So putting critical variables into a register for the duration of a running sum or sum of products can/could significantly improve both speed and numerical accuracy.
@chenyansong
@chenyansong 7 месяцев назад
Long is useful in 16-bit era where it was only way to get a 32bit integer
@erbenton07
@erbenton07 Год назад
When we switched from 32 bit to 64 bit i never understood why long just didn't become 64 bits and int stayed at 32 bits
@ADSharpeSr
@ADSharpeSr 7 месяцев назад
I have to push back on this. For application (or userspace library) development, yes you're right. However, there're elements of your list that are in direct conflict with the main usage of the C language, especially in these modern times -large scale, low level projects (OS dev): 1. Extern - Sure, all global variables are extern by default. However, this doesn't necessarily translate to being extern across the entire scope of the overall project. Consider the case of writing a kernel's console/commandline system. For speed, you may not necessarily want to go through a set device driver API for code that's all internal to the kernel (since device driver APIs tend to be for modules). This is also the case when having a system/module/etc that has some parts written in C & other parts written in Assembly language, which happens very often. They're going to need to communicate with each other. You're not going to be able to communicate effectively & efficiently without the use of extern. 2. Long, Int, et al - This is where you need to take the C standard & combine it with the ABI for the specific platform that you're targeting. Longs & Ints are NOT the same thing. Long is literally a "long int". This means that on platforms where they're not of the same size, the long is guaranteed to be bigger. While they shouldn't be the same size in the first place, reasons of practicality contribute to them being the same size on some platforms -which shapes the ABI. 3. Register - You absolutely don't want your compiler to optimize your code in all instances of writing the lower levels of your kernel nor how different parts of the kernel communicate with other parts. Some parts? Maybe. But all parts? Absolutely not. The kernel needs to guarantee as much as possible, since the kernel is the foundation that everything is standing on. For the parts that don't need guarantees, sure let the kernel optimize those parts. I would also say that if you have students that're new to programming C isn't the best language to start them on. If you want them to grasp the concepts early, start them on BASIC. If you want them to be productive early & don't want to start them off with a lot of baggage, then Python (as much as I loath that language).
@logiciananimal
@logiciananimal 2 года назад
I seem to remember that sizeof is actually an operator not a keyword for some reason.
@JoseIsary
@JoseIsary 7 месяцев назад
"extern" is still so useful, the reason: serves for declaring global variables but not to define them, without it, you define and declare them. Nowadays without extern would be impossible to use: "stdin" and "stdout" globals variable, which are share to any source file that includes "stdio.h"
@clevor1561
@clevor1561 8 месяцев назад
When developing for the TI-84 Plus CE, you can't rely on the size of an int being 32-bits wide. The eZ80 is a weird backwards-compatible version of the Z80 processor, and the eZ80's 2-byte long registers are now 3 bytes long. The size of an int changed to 24 bits because it fits the size of the multibyte registers. There is some work being put in to add 48-byte "short long long" numbers as well. It is strongly recommended to use the *unsigned* integer types as specified in stdint.h because it is a little faster to do unsigned arithmetic on the (e)Z80. There is also a floating-point implementation, but there isn't a double-precision floating point implementation yet. The double type is an alias to a float, but a double precision floating point implementation, if made, would probably get the name long double. However, TI conveniently provides routines for 14-DIGIT precision floating point values in their OS.
@mrcjproject
@mrcjproject 2 года назад
For me auto and restrict keyword is useless
@PhilipSmolen
@PhilipSmolen 2 года назад
auto and register. Some people say volatile is obsolete, but I still like that one!
@Kirillissimus
@Kirillissimus 2 года назад
What about "inline"? It is probably even less useful tan "register". But "auto" is the clear winner here of course. I am sure that if GCC's C compiler would drop its support for the keyword right now or just replaced it with the C++ interpretation then at least 99.9999% of developers would not even notice.
@blooddude
@blooddude 2 года назад
extern is extremely important, it allows you to access a variable which you haven’t defined!
@feeeshmeister4311
@feeeshmeister4311 2 года назад
In C++, yes, but in C, can’t you do that by default?
@blooddude
@blooddude 2 года назад
@@feeeshmeister4311 not sure, gcc always complains if I don’t declare my extern variables as extern, and I’m writing low level OS code so can’t, and don’t use any C++ features.
Далее
The What, How, and Why of Void Pointers in C and C++?
13:12
The Inline Keyword in C.
16:18
Просмотров 57 тыс.
What's the Best Way to Copy a Struct in C and C++?
13:44
I tried React and it Ruined My Life
1:19:10
Просмотров 124 тыс.
The Ultimate Tier Programming Tier List | Prime Reacts
26:57
What is a Monad? - Computerphile
21:50
Просмотров 600 тыс.
why do header files even exist?
10:53
Просмотров 392 тыс.
How different are C and C++? Can I still say C/C++?
10:25
How to Check Your Pointers at Runtime
14:12
Просмотров 31 тыс.