The Most Useless Keyword in C?

  Рет қаралды 68,581

Jacob Sorber

Jacob Sorber

Күн бұрын

Patreon ➤ / jacobsorber
Courses ➤ jacobsorber.thinkific.com
Website ➤ www.jacobsorber.com
---
The Most Useless Keyword in C? // The C language has a lot of keywords. Most are pretty useful, but as languages evolve some keywords become less useful, and this is definitely the case in C. This video takes you through a few examples of keywords that you may never need to use as a C programmer.
Related Videos:
extern: • Understanding the Exte...
stdint.h: • Better Portability wit...
***
Welcome! I post videos that help you learn to program and become a more confident software developer. I cover beginner-to-advanced systems topics ranging from network programming, threads, processes, operating systems, embedded systems and others. My goal is to help you get under-the-hood and better understand how computers work and how you can use them to become stronger students and more capable professional developers.
About me: I'm a computer scientist, electrical engineer, researcher, and teacher. I specialize in embedded systems, mobile computing, sensor networks, and the Internet of Things. I teach systems and networking courses at Clemson University, where I also lead the PERSIST research lab.
More about me and what I do:
www.jacobsorber.com
people.cs.clemson.edu/~jsorber/
persist.cs.clemson.edu/
To Support the Channel:
+ like, subscribe, spread the word
+ contribute via Patreon --- [ / jacobsorber ]
Source code is also available to Patreon supporters. --- [jsorber-youtube-source.heroku...]

Пікірлер: 607
@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.
@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.
@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 ?
@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 7 ай бұрын
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 6 ай бұрын
@@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.
@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.
@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 7 ай бұрын
Very useful comment
@niggacockball7995
@niggacockball7995 7 ай бұрын
Thanks
@realdragon
@realdragon 7 ай бұрын
That's actually cool, I like there's backward compatibility even if it's something from 400 years ago
@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.
@0x007A
@0x007A 2 жыл бұрын
Some of those "useless" keywords are for systems-level programming and are still used today.
@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.
@DavidCourtney
@DavidCourtney 2 жыл бұрын
Interesting, I didn't even know auto existed to be honest.
@xcoder1122
@xcoder1122 6 ай бұрын
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 5 ай бұрын
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.
@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
@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.
@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 6 ай бұрын
"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.
@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
@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.
@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.
@xcoder1122
@xcoder1122 6 ай бұрын
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.
@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
@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 Жыл бұрын
Sometimes embedded system specific compilers treat register differently that does speed up operations.
@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
@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.
@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.
@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.
@CR3271
@CR3271 6 ай бұрын
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.
@zackyezek3760
@zackyezek3760 6 ай бұрын
“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.
@yolamontalvan9502
@yolamontalvan9502 5 ай бұрын
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?
@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 7 ай бұрын
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
@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.
@StopBuggingMeGoogleIHateYou
@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 6 ай бұрын
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 6 ай бұрын
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?
@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++.
@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
@albertome4109
@albertome4109 6 ай бұрын
Hi. I do not understand the useless of return keyword/statement. If anywhere in int myfunc(int a, int b) i put return(-1); this is clear to human reader and to compilers. Or still you want to advocate structured programming ?
@aaaowski7048
@aaaowski7048 Жыл бұрын
idk how fedora's gcc is configured, but gcc doesnt let me compile globals if i dont use the extern keyword. not the case on ubuntu tho as for register, i think there might be a difference in speed if you have more local variables than free registers. like if you have 100 variables but theres one you will use constantly- you hint to the compiler that the one you will use the most should be kept in a register. methinks. ill try that one later on when i am on my coding machine
@garriganstafford9113
@garriganstafford9113 6 ай бұрын
Don’t you have to mark declarations as “extern” for global variables in headers? I always have to and pretty sure I get errors when I don’t.
@ethanboulanger9984
@ethanboulanger9984 2 жыл бұрын
I took a microcontrollers course a year ago and we wrote everything in C. I remember we made use of the external keyword quite oftener but I don’t remember exactly why. I think it had something to do with using the same variable in several different files.
@eyesoars9212
@eyesoars9212 6 ай бұрын
Yup. It generally means don't mangle the name (viz., C++ name mangling), so that it can be linked to other files that use the same symbol name. In C, if a variable is declared in a shared header file, the files that pull in a symbol defined there will pull in the same symbol. Extern guarantees that if the symbol is defined elsewhere (i.e., in another module), that one will be shared. It's somewhat-sort-of the opposite of 'static' which guarantees that an otherwise apparently common variable declared in different modules will NOT be shared with other files/modules. (The meaning of 'static' in C is again different than that in C++.)
@FraggleH
@FraggleH 5 ай бұрын
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.
@TheVertical92
@TheVertical92 2 жыл бұрын
0:56 Must be 34 keywords then. Bcs you have unsigned two times in the list
@reneejones6330
@reneejones6330 6 ай бұрын
Long is guaranteed to be able to hold an address. How do you know what size you need for that?
@GRBtutorials
@GRBtutorials 2 жыл бұрын
0:47 Actually, you counted correctly, it’s just that “unsigned” is repeated.
@brianhginc.2140
@brianhginc.2140 6 ай бұрын
@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.
@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 6 ай бұрын
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.
@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.
@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?
@ReinholdOtto
@ReinholdOtto 2 жыл бұрын
"auto" might be useful as a documentation device, if you use an automatic variable where in similar constellations in the program it is static.
@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
@RossComputerGuy
@RossComputerGuy 2 жыл бұрын
With long, I believe that stdint uses long but that depends on which libc you use. With extern and register, I use them a lot with kernel programming.
@alerighi
@alerighi 6 ай бұрын
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...
@johnsmith1953x
@johnsmith1953x 6 ай бұрын
*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 6 ай бұрын
@johnsmith1953x You mean "Controls to manual, captain, I'm taking over"
@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 KZbin will flag it as spam) Question 1.12 talks about the "auto" keyword.
@nngnnadas
@nngnnadas 2 жыл бұрын
I might say register, maybe unless you work on embedded (especially since the compiler might ignore you).
@justwatching6118
@justwatching6118 2 жыл бұрын
Class I never use that in C 😂😂
@avirukbasak
@avirukbasak 2 жыл бұрын
I had to use extern in a separate global variables header file (clang 13), otherwise the compiler kept screaming that it couldn't find the variable.
@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.
@itsmaxim01
@itsmaxim01 5 ай бұрын
extern is useful in header files for declaring stuff that works both in c and cpp
@gblargg
@gblargg 6 ай бұрын
How about int? I can't think of any case where you need it. I believe every place you would need 'int' you can use 'signed' (or 'unsigned') alone since int is implied.
@brunoleite3958
@brunoleite3958 2 жыл бұрын
That was unexpectedly chaotic and I loved it
@Mr4NiceOne
@Mr4NiceOne 2 жыл бұрын
If you build for Windows, you sometimes need extern to get some Windows' apis working, like dwrite for example.
@skgleba
@skgleba 2 жыл бұрын
I use 'register' all the time to access i.e cache configuration or the chip debug options or stuff like the control bus of the cpu im working with. Sure, i could just inline some assembly but i find using 'register' makes the code cleaner.
@fifa_football_moments
@fifa_football_moments 2 жыл бұрын
Hey Jacob. Could you please make a video on memory sections with examples ?? Like what type of variables are stored in which type of memory?
@xequals-pc1wl
@xequals-pc1wl 6 ай бұрын
The 'C' language doesn't say anything about where variables are stored. It depends entirely on the compiler and architecture.
@Luxalpa
@Luxalpa 2 жыл бұрын
What's the usage of the `signed` keyword? I never needed it.
@Kirillissimus
@Kirillissimus 2 жыл бұрын
Some projects have their compiler set up to make "char" unsigned by default. On some architectures with some compilers it is the default. I never use it though because I only use "char" for text strings anyway because for numbers uint8_t/int8_t are much easier to read. This way all the "signed" and "unsigned" mess is hidden inside the stdlib headers.
@tagon35
@tagon35 5 ай бұрын
I know it was a joke but return does seem like it could be removed in many cases. instead of returning a value adjust a value at a provided address. this could theoretically reduce cycle time but is it worth it? probably not.
@Hellohiq10
@Hellohiq10 2 жыл бұрын
Nice video!
@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.
@giannimariani9744
@giannimariani9744 5 ай бұрын
You can't take the address of a register variable. It can be used to say, I don't want to alias this variable...
@logiciananimal
@logiciananimal 2 жыл бұрын
I seem to remember that sizeof is actually an operator not a keyword for some reason.
@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 6 ай бұрын
Auto is nice in C++, should of used it in Java and C# over var.
@darcyjane8515
@darcyjane8515 2 жыл бұрын
I despise "const". Don't tell me what I can and can't do! 😅
@lsatenstein
@lsatenstein 2 жыл бұрын
I code with Linux and the int is 64 bits in size.. The long is 64 bits, and the long long is 96 bits. The long attribute has to be used with strlen(), and other string functions.. I usually have to cast the output of strlen() ;
@dahalankur
@dahalankur 2 жыл бұрын
I can't believe you didn't talk about `inline` here!
@user-mx6gi8fy6j
@user-mx6gi8fy6j 2 жыл бұрын
Isn't extern necessary for errno
@JamesJones-zt2yx
@JamesJones-zt2yx 6 ай бұрын
Yup. Nowadays, "register" just means "you can't take the address of this".
@SianaGearz
@SianaGearz 5 ай бұрын
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.
@saumyacow4435
@saumyacow4435 6 ай бұрын
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.
@KayOScode
@KayOScode 6 ай бұрын
Auto is an artifact of the B days. Also, can anyone explain to me why B used extrn instead of just adding the e and spelling it correctly: extern
@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.
@peterg76yt
@peterg76yt 8 ай бұрын
'auto' is genuinely superfluous; the others may be unnecessary with some compilers or linkers but definitely required with others.
@Jplaysterraria
@Jplaysterraria 2 жыл бұрын
One small detail you didn't mention about register variables is taht you cannot take the address of them. When that is relevant, I don't know.
@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.
@lef1970
@lef1970 2 жыл бұрын
I use long all the time when moving data around with a void pointer because sizeof(long) == pointer size on the machines I use (ILP 32 and LP64 memory model).
@momoanddudu
@momoanddudu 5 ай бұрын
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.
@ksbs2036
@ksbs2036 2 жыл бұрын
I once used a specialized C compiler for high performance custom processor that recognized Global registers. The register keyword enabled this behaviour. For extreme performance the global register enabled custom-hardware level capability. I've never used the"auto" keyword in the 200kloc of C code I've written
@stevencolborne6845
@stevencolborne6845 6 ай бұрын
A common complaint about c, it is not portable from processor to others. It is unfortunately common to use local keywords to pretend portability.
@m8nu
@m8nu 2 жыл бұрын
0:46 -> unsigned is listed twice. So they are only 34 keywords?
@ocrap7
@ocrap7 2 жыл бұрын
I think auto is the most useless as aren't all variables already "auto" by default?
@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
@vcv6560
@vcv6560 6 ай бұрын
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.
@brunoais
@brunoais 2 жыл бұрын
My bet: Register Even though it sometimes causes changes in code, they are usually only at -O0. most of the times, when using -O1 or more, register is actually considered in all compilations by default
@rogerlevasseur397
@rogerlevasseur397 6 ай бұрын
back in the PDP-11 days of C with limited CPU resources and analysis of the C program by the compiler, register was useful as a hint to the compiler. These days the architectural offerings are much improved for having more registers and with more CPU power and RAM, more compiler analysis can take place.
@applesushi
@applesushi 2 жыл бұрын
I haven't written C code in about 20 years and this still amused me.
@erbenton07
@erbenton07 11 ай бұрын
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
@psykikteevee
@psykikteevee 6 ай бұрын
Pre-C23 auto, if that still counts. For modern C, register but I'm not sure if that one can still be useful with certain compilers.
@HansBezemer
@HansBezemer 5 ай бұрын
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.
@fabiogulmini4664
@fabiogulmini4664 2 жыл бұрын
I really love your voice, your editing and in general the style of your videos, but with this one I noticed that even if the length is just over 10 minutes, the actual leaderboard started at 3 minutes, which in my opinion is a bit to long Great content btw
@xequals-pc1wl
@xequals-pc1wl 6 ай бұрын
@fabiogulmini4664 Yeah, I thought he'd never shut up and get on with it.
@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 5 ай бұрын
@@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.
@clevor1561
@clevor1561 6 ай бұрын
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.
@raghavsrivastava2910
@raghavsrivastava2910 2 жыл бұрын
I think the register keyword is not completely useless as there are limited registers and if we have too many variables then by putting the register keyword in front of the frequently used/important variables can help the compiler optimise better. Or maybe with compiler optimization turned on it will automatically prioritise the important variables to be loaded in the registers???
@JacobSorber
@JacobSorber 2 жыл бұрын
In my experience, on modern compilers, the optimizer seems to get right, nearly always.
@raghavsrivastava2910
@raghavsrivastava2910 2 жыл бұрын
@@JacobSorber Thanks for replying.
@joseisary
@joseisary 6 ай бұрын
"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"
The What, How, and Why of Void Pointers in C and C++?
13:12
Jacob Sorber
Рет қаралды 51 М.
NERF WAR HEAVY: Drone Battle!
00:30
MacDannyGun
Рет қаралды 47 МЛН
Must-have gadget for every toilet! 🤩 #gadget
00:27
GiGaZoom
Рет қаралды 12 МЛН
The child was abused by the clown#Short #Officer Rabbit #angel
00:55
兔子警官
Рет қаралды 24 МЛН
Пробую самое сладкое вещество во Вселенной
00:41
Running a Buffer Overflow Attack - Computerphile
17:30
Computerphile
Рет қаралды 2 МЛН
Faster than Rust and C++: the PERFECT hash table
33:52
strager
Рет қаралды 521 М.
What's the Best Way to Copy a Struct in C and C++?
13:44
Jacob Sorber
Рет қаралды 33 М.
RISC-V Week: 7 days only using RISC-V computers
25:40
ExplainingComputers
Рет қаралды 197 М.
How to Check Your Pointers at Runtime
14:12
Jacob Sorber
Рет қаралды 30 М.
why do header files even exist?
10:53
Low Level Learning
Рет қаралды 373 М.
NERF WAR HEAVY: Drone Battle!
00:30
MacDannyGun
Рет қаралды 47 МЛН