A const int is not a constant.

  Рет қаралды 66,312

Jacob Sorber

Jacob Sorber

Жыл бұрын

Patreon ➤ / jacobsorber
Courses ➤ jacobsorber.thinkific.com
Website ➤ www.jacobsorber.com
---
A const int is not a constant // seriously. It's one of the oddest things about C, but it's true. In this video, I'll show you a few examples.
***
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...]

Пікірлер: 349
@johnheaney3349
@johnheaney3349 Жыл бұрын
Macros are not C "constants"; they are literals. They compiler does not even see macro definitions because they are preprocessed before compilation. They are only constants in the sense that literals are a type of constant, but again, the compiler does not see or process macros. If you look at the preprocessor output, the macros are completely gone. Enums are the only symbolic constants in C. They are evaluated by the compiler, so they are part of the C source code, but are literals in the code. The definitions do not take up code space. Code space is only used inline when they are used in the code in place of literals. Literals cannot be accessed by address in C, it would kind be nonsensical to do so. Literals only take up code space inline with the code. They can only be addressed if the literal is in an initializer for a variable. Then the literal value can be shared, directly or indirectly, because the variable has an address. The const keyword is for access control for variables and parameters. The literal values that form the initializers of variables can then be shared because the address is part of the code space and that address can be shared. That means for static and global variables, the initializer is evaluated at compile time and that instance is stored with the code. For non-const variables, that structure is copied to a RAM location at startup, so the storage is really doubled. There's a copy in code and then in RAM. This is true for locals, as well, except the RAM copy occurs upon function entry, not at program startup. I mainly write firmware these days, so const has a special meaning in firmware development, assuming the code is running in flash. The code, including initialized variables, is in flash, which is non-volatile memory. They truly cannot be modified at runtime. It is more than just access control. In firmware development, vendors ship libraries with gobs and gobs of macro definitions for constants. The main reason for this, I believe, is that all of those definitions simply go away after the preprocessor phase of the build. That's a good thing because 99% of those definitions go unused. Although that isn't conditional compilation in the logical sense, it kinda is because the definitions are only selected when they are invoked. In that sense, all macros are conditional compiling. Contrast that with enums, which take up no space in your code image, but are still compiled. Contrast that with const variables, which are both compiled and take up space in your code image. I hope that is not too confusing. I find much of this hair splitting doesn't matter unless you are writing firmware that runs in flash. In that case, understanding this stuff is important because RAM and ROM are both precious resources.
@JacobSorber
@JacobSorber Жыл бұрын
Thanks. And, I completely agree. It mostly doesn't matter, until it does, and then it makes people a little crazy. Thanks for the detailed explanation.
@HansBezemer
@HansBezemer Жыл бұрын
Thanks for cleaning up the ontology of C used here. I recently did a KZfaq on every stage of the C compilation process and I can only concur. BTW, thank you for pointing out the benefit of the "const" keyword I never thought of! Learned something today ;-)
@ed_iz_ed
@ed_iz_ed Жыл бұрын
I think the most confusing aspect I ever found with C was string initialization, string literals can mean different things in different places, char[] and you defined a stack allocated string, char* and you defined a read only string allocated in static memory
@0LoneTech
@0LoneTech Жыл бұрын
C macros aren't necessarily literals, they're simply text substitutions. Whether that text forms a literal or not is a different matter. Sadly, this video just tried to hammer in "const is not constant", not say what it is, nor what was expected of constants. One has to deduce that what was intended was a compile time constant expression. Indeed, const isn't that; const marks read only memory locations. That's a sensible definition of a constant value in many cases, but it isn't compile time (the samples wouldn't be known until link time).
@ed_iz_ed
@ed_iz_ed Жыл бұрын
@@0LoneTech also not even read only memory locations, a const int * doesn't mean pointer to constant integer, but rather pointer to integer which can't be used to write, but someone else might
@greg4367
@greg4367 Жыл бұрын
Up for a challenge: Enplane to the newbie C programmer the differences in use of volatile , const, and static as applied with scope global, file global and function. Good luck. Fifty years of coding in C (yes, it is still my goto language) I still sometimes get tripped up. But all languages have these problems, as in: Throw the horse over the fence a bale of hay.
@DerMarkus1982
@DerMarkus1982 Жыл бұрын
Syntax error in line 1: Unexpected token(s) "a bale of hay" at end of statement. Compiling anyway. ... Success! Executing. ... Failed! [ log from PhysicsEngine: object "horse" too heavy!] 😂
@KangJangkrik
@KangJangkrik Жыл бұрын
Me: **removes exception from PhysicsEngine* Problem solved :)
@tk36_real
@tk36_real Жыл бұрын
"differences in use of volatile, const" - there are none, they are syntactically equivalent
@paulc2448
@paulc2448 Жыл бұрын
label 'language' was undefined.
@dangnabbit1379
@dangnabbit1379 Жыл бұрын
Weird use of object notation but ok
@ABaumstumpf
@ABaumstumpf Жыл бұрын
This is a Video that tries to talk about the intrinsics and fundamental behaviour of 'C' - but fails horribly at that. What do you mean by "is a constant" ? Cause C does not have anything that "is a " constant. You can have a "constant expression", or the keyword const that is a type-qualifier. "const int A = 10;" IS constant. The compiler is allowed to move it to a read-only section and if the address of 'A' is not taken, allowed to omit it. "we could use pointer tricks to actually change the Value of 'A'" No you can not - that is by definition undefined behaviour and most compilers will not let you do that but just ignore your code that attempts to do so. Feel free to try it out... or rather: YOU REALLY SHOULD HAVE TRIED IT BEFORE making those false statements. "const int A = 10; const int B = A + 1;" - yes, that is not allowed cause it is not a "constant *expression*", not cause it is "not a constant". This is a quirk of global lifetime and initialisation. The most frustrating thing is that you are #constantly talking about "a constant" which is just not a thing that exists in C.
@euchre90
@euchre90 Жыл бұрын
If "const int A = 10;" is not at file scope, you actually CAN use pointer tricks, since the variable is allocated on the stack rather than the read-only data section. At file scope this will just cause a segfault.
@programmertotherescue
@programmertotherescue Жыл бұрын
@@euchre90 Just writing random code and waiting until a segfault happens, and then changing the part of the code that's causing it is a bad way to write C. Doesn't matter if `A' is in file scope or not, using an lvalue with a non-const qualified type to modify an object defined with a const qualified type is still undefined behavior.
@programmertotherescue
@programmertotherescue Жыл бұрын
"C does not have anything that "is a " constant": This is a pretty misleading statement, IMO, when there's literally a section in the standard [called `Constants'] (see n1570 §6.4.4) that describes the syntax, constraints and semantics of constants.
@eddiebreeg3885
@eddiebreeg3885 Жыл бұрын
Cppreference: "Constants, by their simplest definition, are values that do not change." const x is, quite literally, a constant. If you declare a macro equal to 10, that's a literal expression (and yes obviously it is a constant expression).
@_Omni
@_Omni Жыл бұрын
Cppreference: C adopted the const qualifier from C++, but unlike in C++, expressions of const-qualified type in C are not constant expressions.
@eddiebreeg3885
@eddiebreeg3885 Жыл бұрын
@@_Omni A constant and constant expression are two different things in C++. The first simply is something that shouldn't change, the second is something that is known at compile time.
@_Omni
@_Omni Жыл бұрын
@@eddiebreeg3885 yes
@xarcaz
@xarcaz Жыл бұрын
It IS a constant. Just not a compile-time constant (such as pre-processor defines, enum values, and C++ constexpr values).
@reinhold1616
@reinhold1616 Жыл бұрын
pre processor defines are not compile time :)
@xarcaz
@xarcaz Жыл бұрын
@@reinhold1616 It depends on the context. As long as it's a numerical expression solely consisting of literals and regular operations (i.e. a constant expression) it will be evaluated at compile-time.
@reinhold1616
@reinhold1616 Жыл бұрын
@@xarcaz i meant that defines are evaluated by the pre processor which runs before the compiler
@xarcaz
@xarcaz Жыл бұрын
@@reinhold1616 Oh, I definitely agree with that. I just meant the common constant expression usage cases, not all macro cases. :)
@tomaszstanislawski457
@tomaszstanislawski457 Жыл бұрын
btw... `constexpr` will be added to upcoming C23 standard
@knightflyer909
@knightflyer909 Жыл бұрын
It is worth remembering that when coding for many microcontrollers "const" will place the value in the program store (often times Flash). From a practical point view this means the value will be read-only. This just an addition to already excellent video.
@jftsang
@jftsang Жыл бұрын
Does this give a performance boost?
@harrytsang1501
@harrytsang1501 Жыл бұрын
@@jftsang only if you know exactly what you’re doing. Evaluate the bottleneck of your program before things like this actually make a difference. Being in flash not ram is like a literal, where you cannot write to it and it lives in the space that stores your program. Makes sense if you have limited ram but could be slower if the architecture does not cache it temporally
@0xO2
@0xO2 6 ай бұрын
@@jftsang on microcontrollers there is a limited RAM, while program and const data is usually stored in a ROM.
@xcoder1122
@xcoder1122 6 ай бұрын
Actually on any modern computer the compiler will place a const variable into a section of the binary image that is loaded into memory pages that are later on read-only. Running this code on my computer will crash the executable with EXC_BAD_ACCESS (SIGBUS): #include const int A = 10; int main( ) { int * aPtr = &A; *aPtr = 20; return EXIT_SUCCESS; } So the variable truly is read-only. Even if you can compile code that would write to it, this code won't work at runtime. Even accidentally writing to it's memory with memcpy() would still crash. On all modern systems memory pages can be tagged read-only and this is enforced by the hardware. But that's not where program code is stored. Program code is also stored in read-only pages but on top of that, they have the executable flag set, as modern CPUs refuse to run code from memory pages that don't have that flag set. This is a security feature, so even if an attacker manages to load code into memory and somehow convinces the CPU to jump to that memory location, unless those pages were marked for execution, the process will just crash and not runt hat code.
@maxaafbackname5562
@maxaafbackname5562 2 ай бұрын
No, it is not stored in program space. The are placed in read only data space. And that can still be RAM in stead of flash memory. If you want them to be placed in program space, for that micro controllers you have to specify that with a controller specific attribute/keyword. PROGMEM is an example. Very commonly used with string literals.
@georgecop9538
@georgecop9538 Жыл бұрын
2:17 You can #undef and then redefine with a new value. It's not really a constant, just a macro
@HansBezemer
@HansBezemer Жыл бұрын
When preprocessed it is a literal. Believe me.
@johnheaney3349
@johnheaney3349 Жыл бұрын
It's a constant in the sense that it does not change over the life of the application runtime, even if it has multiple value definitions over the life of the compilation.
@maxaafbackname5562
@maxaafbackname5562 Жыл бұрын
@@johnheaney3349 no, not true. The value _can_ change. Only the code, at that point, is not allowed to change it. Especially when the variable is both declared const _and_ volatile, you know the value _will_ change.... Read-only does not imply it will not change.
@johnheaney3349
@johnheaney3349 Жыл бұрын
@@maxaafbackname5562 I think you may have been replying to the wrong comment. This one is about macros, not variables. Macro values can be changed over the span of preprocessing a file, but the literal values output by macros cannot be changed at compile time and certainly not runtime. This comment thread is not about variables.
@taragnor
@taragnor Жыл бұрын
All the preprocessor does is just replace every instance of the token with whatever you defined it as. It is really as simple as that, a basic copy/paste. #define A 10 is equivalent to just typing 10 everywhere you typed A. It just takes the magic number out of the code itself and puts it earlier, but when your code compiles it just sees it as though you typed 10 everywhere.
@Siger522
@Siger522 Жыл бұрын
Actually literals in C (i.e. what #define's produce) do have a type - which can be affected with suffixes like U, L, LL, Z, etc. - and the compiler is aware of it. Might be an interesting topic for a video.
@Minty_Meeo
@Minty_Meeo Жыл бұрын
An uncommon example of this: character literals (a string contained within single quotes, e.g. 'a' or 'next') are of type int according to the C standard. This means you can never make a 64-bit character literal when int is 32-bits wide if using a conformant compiler, such as GCC. I bring this up because I have seen a non-conformant compiler (MetroWerks) which allowed this.
@arthur1112132
@arthur1112132 Жыл бұрын
@@Minty_Meeo Doesn't literal casting allow to do this ? #define A ((uint64_t)'a') Or maybe i don't get what you mean :/
@Minty_Meeo
@Minty_Meeo Жыл бұрын
@@arthur1112132 Afaik, 'a' will still be an int32. Casting it to int64 is simply type widening. A character literal which is too big still gets truncated to an int32 regardless.
@arthur1112132
@arthur1112132 Жыл бұрын
​@@Minty_Meeo Oh yeah so a literal character won't ever use the whole 64 bits. That make sense.
@0LoneTech
@0LoneTech Жыл бұрын
I've literally fixed bugs changing 1
@maxaafbackname5562
@maxaafbackname5562 Жыл бұрын
10 is a integer literal. And that is by definition constant. In C a constant (variable) is not the same as a literal.
@HansBezemer
@HansBezemer Жыл бұрын
True. It's a "read only integer variable". If you want a true literal, you use #define. K&R was right.
@donjonmaister
@donjonmaister Жыл бұрын
I was about to comment that, but you beat me to it. Yes, you are absolutely right 😁👍
@sb_dunk
@sb_dunk Жыл бұрын
@@HansBezemer It's still only kind of constant as mentioned in the video due to the fact that you can just edit the memory holding the const int, e.g. const int x = 10; int* y = &x; *y = 11; x is now 11
@TheRobbix1206
@TheRobbix1206 Жыл бұрын
@@sb_dunk Don't do that, in most case it will crash !!! Because the constant might be put into a read-only location meaning that you would segmentation fault on that (that's why using const_cast in C++ is really something you should avoid) Even more it can create undefined behaviour into your program because you said that x is now 11 at the end.... Well bad news, you don't know, you fall under the categorie of undefined behaviour, which means anything can happen, and compiler optimization might give you wrong, because the compile can assume that this value didn't change so if you tried to display it even after you though you modified it, might still be considered as 10 by the compiler !
@sb_dunk
@sb_dunk Жыл бұрын
@@TheRobbix1206 Oh interesting... I assume this behavior is OS-dependent?
@eriks2962
@eriks2962 Жыл бұрын
Hey Jacob, I'm a colleague from a couple hours north on I85. I love the idea of talking about const and literals in C. But be careful that students will watch videos and take the content as gospel. Then C instructors will need to spent 30 minutes clearing up misconception introduced in this video. And then they won't believe you on your next video which is a shame because they are usually pretty good. So it's better to get them right the first time. The fundamental thing is that there is no such thing as a constant in C. It's a word we still use colloquially because it's a good short hand. And It's unfortunate that K&R used the word constant in their original grammar. But the programming world has been calling them literals for decades now to clarify the meaning. So you have literals and variables of const type. And they are not interchangeable in the language. You can't write on a const int in C. Even if you do weird pointers things to get the right address. Writing on a const in C is undefined behavior. It may work on some systems, but it's not C standard. I've seen architectures where the const variable get mapped to ROM, or a RO data segment, or just to a regular segment of memory. And so in practice I've seen writing to a const with weird pointer tricks that would change the value, be ignored, or lead to segfault depending on the architecture. I like the idea, but the execution is, I am afraid, confusing to students. I'll gladly review scripts of video if you want. Not that I know better, I probably don't. But sometimes, two sets of eyes are better than one! PS: And I understand the difficulty of crafting a perfect video! I recorded an entire map/reduce video lecture where I mixed up cross product and cartesian product. My students had never been so confused!
@programmertotherescue
@programmertotherescue Жыл бұрын
"The fundamental thing is that there is no such thing as a constant in C": Well, what exactly makes you think so? The C standard literally has a section that talks about constants (see n1570 §6.4.4). "But the programming world has been calling them literals for decades now to clarify the meaning": Then the "programming world" has been using using incorrect terminology. `Constants' and 'literals' are not synonymous terms in C. The C standard (at least C99, C11 and the draft n2310) doesn't even define what a `literal' is.
@nicholaswood3250
@nicholaswood3250 Жыл бұрын
In C (and any language really), the guardrails are there for you and not the machine. Everything depends on your willingness to engage with the languages’ constraints in good faith (unless you’re just breaking things for fun)
@llllNEOllllchannel
@llllNEOllllchannel Жыл бұрын
What do you mean under "constant is not really constant but read only entity since we intialized it"? How else would you describe or define constant if it is not just read-only entity?
@v0id_d3m0n
@v0id_d3m0n Жыл бұрын
a constant would have to be assigned to immediately when it is declared, whereas a read-only value could also be assigned to in a constructor
@llllNEOllllchannel
@llllNEOllllchannel Жыл бұрын
@@v0id_d3m0n calling a constructor is basically "assignment after declaration immediatly". Those are the same things. I still don't see any difference.
@Pi7on
@Pi7on Жыл бұрын
As i understand it, what you're doing buy initializing "const A = 10" is impeding yourself from assigning a different value to the A variable, essentially granting yourself read only permission to the A variable. What you would still be able to do tho, is create a new int pointer, and assign it the address of A: "int *addr = &A". Then you could dereference that pointer and change the value it points to: " *addr = 42 ". This way, you effectively changed the value of A.
@Littlefighter1911
@Littlefighter1911 Жыл бұрын
@@v0id_d3m0n You and OP of this video are redefining what constant means in C. That's like learning someone else's language and telling them they're using their own words wrong, because you have a different concept of what that word means in another language. (For example, you're Japanese and use the term "hamburger", see an American eat something he calls "hamburger" and try to correct him that "hamburger" is just the patty)
@mk72v2oq
@mk72v2oq Жыл бұрын
You can have a read-only variable that changes. E.g. some device mapped into the memory, which returns its own data on read operation at given address, but completely ignores the write operation.
@adecy9669
@adecy9669 Жыл бұрын
Great video, in embedded systems we usually use "volatile const uint32_t *reg = 0x04000000u;" to describe a read-only register (like a hypothetical UART RX DATA register). It's not possible to write to the register, but we can read from it, and each time we read it we can get a different value ! And the volatile make it even funnier.
@dj_chateau
@dj_chateau 10 ай бұрын
Wait, why is that funnier? 🤔
@10vid5
@10vid5 Жыл бұрын
I've always liked the *EQU* assembly directive for defining numeric literals. More powerful than *#define* for numbers, you don't have to guard your numeric expressions with parentheses. I'm surprised they didn't bring it over yet.
@sameerplaynicals8790
@sameerplaynicals8790 Жыл бұрын
Hello. What if someone uses mmap to allocate memory with the flags PROT_READ and PROT_WRITE, modifies the value of the pointer, then uses mprotect to just change the flags to PROT_READ? Wouldn't that pointer behave like a constant?
@_modiX
@_modiX Жыл бұрын
const int TEN = 10; // in case ten fluctuates
@HansBezemer
@HansBezemer Жыл бұрын
It does when using floating point. ;-)
@andrewporter1868
@andrewporter1868 Жыл бұрын
@@HansBezemer Ah, but you forgot the other asterisk which is that this only occurs if using floats where the float encoding cannot represent all fractions because of the base being coprime with the denominator. By the way, it is possible to represent all integers in [0, 2**64] using primorial bases, in this particular case, base (pi(2**64))# where n# denotes the product of all primes prime(1)...prime(n), and pi(n) is the prime counting function. You can get the same using factorial, but primorial here is far more economical since n! grows much faster than n#. Using base (pi(2**64))# guarantees that all fractions (0, 2**(-64)] are guaranteed to have at least one common factor, and therefore a finite representation.
@programmertotherescue
@programmertotherescue Жыл бұрын
Reposting my comment, because my comments keep disappearing for some reason. At 04:16 "printf("&A = %p ",&A);" I'd recommend a cast to a pointer to void if you're using the %p conversion specifier. Sure it might seem to work how it's supposed to on most implementations even without the cast, but to be pedantic, this is undefined behavior. The %p conversion specifier expects a pointer to void, and if any argument is not the correct type for the corresponding conversion specification, the behavior is undefined. From the C standard draft n1570 (The fprintf function) (didn't write exactly where it is in the standard draft, because KZfaq doesn't seem to like it if you put a lot of numbers in your comment) (emphasis mine): p The argument shall be a **pointer to void**. The value of the pointer is converted to a sequence of printing characters, in an implementation-defined manner. At 04:30 "We could use pointer tricks to actually change the value of A": Then you'll invoke undefined behavior. From n1570 (Type qualifiers) (emphasis mine): **If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined**. If an attempt is made to refer to an object defined with a volatile-qualified type through use of an lvalue with non-volatile-qualified type, the behavior is undefined.
@starc0w
@starc0w Жыл бұрын
Now I'm curious to see what Jacob has to say about this!
@ABaumstumpf
@ABaumstumpf Жыл бұрын
"if an attempt is made to refer to an object" Referring to the object is allowed, attempting to modify is not. "const int A = 10; int *ptrA = &A;" is well-defined. only trying to modify it like with "*ptrA = 2" would be UB.
@programmertotherescue
@programmertotherescue Жыл бұрын
@@ABaumstumpf Can you point out where exactly in my comment I said otherwise? The part of the comment you're quoting is a part of the clause from the standard that I quoted and it's irrelevant, since it talks about objects defined with a volatile-qualified type, not const-qualified type. The only relevant part is in the emphasis, which says "If an attempt is made to **modify** an object [...] undefined".
@praktexemplar8082
@praktexemplar8082 Жыл бұрын
Hey Jacob, great video. I for one would actually love to see a video of pointer magic on const variables.
@euchre90
@euchre90 Жыл бұрын
Basically, when the const variable is not at file scope, we can define a pointer and initialize it with the const variable's address, then dereference it and assign a new value to the const variable. This won't work with a file scope const variable because it resides in the read-only data segment of the program, and trying to write to it will cause a segfault.
@praktexemplar8082
@praktexemplar8082 Жыл бұрын
@@euchre90 I understand. Thanks for the info!
@-wx-78-
@-wx-78- Жыл бұрын
This reminds me of Fortran's numeric literals that are actually variables - they can be modified (mostly by accident) when used as subroutine parameters because of “pass by reference” calling convention.
@SassyToll
@SassyToll Жыл бұрын
Thank you, I love your course on C/C++ I have learn so much, I really appreciate what you are doing
@tbird81
@tbird81 Жыл бұрын
Video starts at 3:05
@alias914
@alias914 5 ай бұрын
In embedded C const makes perfect sense. Const means variable is stored in ROM (flash), so you cannot change it's value. You can read it, you can copy it to RAM, but you cannot edit it. int a = 5, stores value 5 somewhere in flash and copies it into RAM in init routine. const int a =5, stores value 5 somewhere in flash and you access a from RAM.
@peircedan
@peircedan 6 ай бұрын
Since you have posted a clarification video I'm surprised you have not changed the title to this one and also have not pinned a link to the clarification (which has far fewer views than this one). I think K&R expressed what a const is quite clearly: "The qualifier const can be applied to the declaration of any variable to specify that its value will not be changed." and they also say: "The result is implementation-defined if an attempt is made to change a const." So your correct when you say that a const is a read only variable. Also, they use the words "consent expression" to refer to a literal or combination of literals with arithmetic operators. They use the words "symbolic constant" to refer to the name part of a simple macro and constant or constant expression when referring to the part the macro will substitute in. It should be apparent that the word constant is used here in different contexts and so It seems to make no sense to say a const int is not a constant. It is a read only variable and in that context it is a constant. K&R (2nd ed) also says the following: "The const and volatile properties are new with the ANSI standard. The purpose of const is to announce objects that may be placed in read-only memory, and perhaps to increase opportunities for optimization. The purpose of volatile is to force an implementation to suppress optimization that could otherwise occur. For example, for a machine with memory-mapped input/output, a pointer to a device register might be declared as a pointer to volatile, in order to prevent the compiler from removing apparently redundant references through the pointer. Except that it should diagnose explicit attempts to change const objects, a compiler may ignore these qualifiers."
@StefanNoack
@StefanNoack Жыл бұрын
TLDW: const int is a constant at runtime, but not at compile time. The value does not even need to be specified in the same compilation unit, so it might not even be known until the program is linked. But it sure won't change at runtime, that's all. The confusion comes from "constant expressions" which are expressions with a value that can be determined at compile time, and that a const int is not.
@lukasschmitt3075
@lukasschmitt3075 Жыл бұрын
#include int main() { const int A = 10; int* a_ptr = &A; printf("%i ", A); *a_ptr = 42; printf("%i ", A); return 0; } Why should A be considered a constant - or are we only talking about file scope?
@StefanNoack
@StefanNoack Жыл бұрын
@@lukasschmitt3075 I mean defining constants is especially helpful for larger projects with multiple files. So you would have the value for the const int in one file but on the usage site the value is not known at compile time. That's why headers and #defines are used for things that need to be known at compile time instead.
@lipcioful
@lipcioful Жыл бұрын
Finally, a great, interesting and professional C content on YT ☺
@KelvinShadewing
@KelvinShadewing Жыл бұрын
I'd love to see how to do that pointer trick. Don't think I'd ever need it, but it sounds fun to learn.
@leokiller123able
@leokiller123able Жыл бұрын
const int i = 5; *(int*)&i = 42;
@Carolus_64
@Carolus_64 Жыл бұрын
Before making a video on "exotic" constexpr please explain the const used with pointer and how to declare a 1) pointer to const variable 2) const pointer to variable 3) const pointer to const variable I'm programming in C 30 years and with exception case 1 I have always to check books or internet to find syntax for cases 2 and 3
@robert36902
@robert36902 Жыл бұрын
Thanks for the video, this is an area where I don't know all the details. Is the C compiler allowed to do optimization for calculations involving variables that are const but not volatile, such as replacing A+1 with 11? Is it allowed to put them in a read-only segment?
@ABaumstumpf
@ABaumstumpf Жыл бұрын
Yes and yes. Also what he says about "const" ... better read up on what "const" actually means - cause there is no such thing as "a constant" in C.
@chri-k
@chri-k Жыл бұрын
“const” just promises the compiler that the variable will not change. The standard is aware that that promise could be broken, so const variables are not allowed into places which require a true constant. And, it can and will just replace occurrences of A with 10 where it makes sense.
@robert36902
@robert36902 Жыл бұрын
Thanks for the replies!
@davidgillies620
@davidgillies620 6 ай бұрын
I find myself coding C-like code in C++ just so I can take advantage of things like constexpr and compile-time array sizing.
@Invisible12345ful
@Invisible12345ful Жыл бұрын
Macro definitions (#define) work well as constants if you are using primitive types such as int, float, etc. and that works well and you should stick to that. Macro definitions can easily be identified by all caps and are easily found on top of files, editors also like to show them in green color. It's a very good way to define constants. Unfortunately it is impossible/impractical to define arrays (strings, structs, etc.) with "#define", however for safety of program sometimes you still want to create array objects that cannot be changed (are immutable). This is where "const" comes handy, because it makes sure nowhere in your program you perform a write operation on your array type variables, hence they become constants.
@HansBezemer
@HansBezemer Жыл бұрын
I've got to see the first program where I use "const" to define a constant. I always use the preprocessor for that - just to keep my sanity. Sure, if you define stuff like: #define PAD TIBSIZ #define STRTOP ((TIBSIZ+PADSIZ)-DOTSIZ) "STRTOP" will probably be inlined like some expression but I've never seen a C compiler barf on expressions like that. It's probably a case of constant folding. Advantage is though that constants are always inlined. It saves you one access to memory. Funny thing - in Forth CONSTANTs are done the "const int" C way. But since most of the expressions in Forth using it (like allocating some static memory) are INTERPRETED it doesn't get in the way. My own Forth compiler though inlines constants by storing them in the symbol table. Expressions USING those constants are mostly resolved by the optimizer that does constant folding. Which is funny since it means the optimizer is in essence part of the syntax ;-) I'm not a great fan of "const". I know it helps the optimizer, but apart from (very) basic functions (which we call "primitives" in Forth) it's more often a pain in the neck (when doing maintenance) than a great help IMHO.
@sophiacristina
@sophiacristina Жыл бұрын
EDIT: Check the answer i received below before reading this comment... Me too, i used to use 'const' before, now i use mostly 'define'... I think the only use of const, to me (at least, i'm not a pro, just hobbyist), is if i need it in the memory... Which i never needed... And seems to be useful only in a data structure , because i can't think about an use for a mere "int". Let's say: struct RGB { unsigned char R, G, B; }; int main() { const RGB Color = { 255, 255, 255 }; const RGB Color2 = { 0, 255, 0 }; return 0; } In this case, having a memory address maybe would be useful... Even if someone still can use define for it... #define WHITE { 255, 255, 255 } The RGB structure would still be able to be modified...
@ABaumstumpf
@ABaumstumpf Жыл бұрын
""STRTOP" will probably be inlined like some expression but " ... as you said - that is a pre-processor step. There is nothing left to inline as it literally just string-replacement. "const int" will actually provide a constant value and, unless you take the address of it, very likely not have a memory address. More likely than not you would be better of with using 'const' but doing so correctly (not with the false explanation of this video) or use enums.
@ABaumstumpf
@ABaumstumpf Жыл бұрын
@@sophiacristina " need it in the memory..." Then you are doing it wrong cause no - your example will not produce what you expect. Those const-structures will nearly 100% not be in memory. And you could not modify those const RGB structs either.
@sophiacristina
@sophiacristina Жыл бұрын
@@ABaumstumpf And ty you again to clarify this to me in this comment too... :)
@lukasbelan2109
@lukasbelan2109 Жыл бұрын
I literally had a technical interview half an hour ago and they asked me this very same question, whether const means constant (of course I said yes)... And youtube of course NOW decides to recommend this.
@jbird4478
@jbird4478 Жыл бұрын
It does mean constant. It just doesn't mean the concept the maker of this video calls "a constant". That seems like a stupid trick question for an interview.
@maxaafbackname5562
@maxaafbackname5562 Жыл бұрын
No, it does not mean "constant". It means "read only". With volatile it can change, without volatile, the compiler can/may assume it is constant.
@primosoma
@primosoma Жыл бұрын
I’m a newbie in C and I’m a bit confused. What do you mean with “constant”? Because for me a constant is a function a->b->a, for example the const function in Haskell. What is a constant in C?
@davidlynch4202
@davidlynch4202 Жыл бұрын
In C a constant is a variable that’s value cannot be changed
@TheRobbix1206
@TheRobbix1206 Жыл бұрын
Ok so this is because the video author, though of some other language constant which can be use where you want, even in the case he mentionned. So a "constant" can refer to two different things depending on the context, in his case, a want to say constant expression, which is a value evaluated by the compiler. The other one is a constant variable, which is a variable which it's value cannot be changed (and I think this is the one you are also thinking about)
@sophiacristina
@sophiacristina Жыл бұрын
When you use define, you are pre-processing, that means, it is a literal, or better, the compiler just swap whatever is written in front of "define something' to anything which is named 'something'. Some people don't even call 'define' stuffs as constant, they normally only call it macro... One of the comments in this video, from John Heaney, points this up. A const int, or const type, opens a space in the memory, but the value at the memory address can't be modified (it can with some "hacks")... Then you are going to ask "but the define also can't be modified', the difference is that define don't open a space in the memory, it is more like a ctrl+c and ctrl+v... For example, this program would compile successfully (c++): #define MAIN int main() MAIN { return 0; } EDIT: Typos., grammar and clarity.
@primosoma
@primosoma Жыл бұрын
@@TheRobbix1206 yes, I mean the const int is technically a constant, but in some cases the compiler doesn’t treat it as such or imposes limits on its use. As I understand it.
@HansBezemer
@HansBezemer Жыл бұрын
In general it is defined as Wikipedia states, that is: "In computer programming, a constant is a value that should not be altered by the program during normal execution, i.e., the value is constant. When associated with an identifier, a constant is said to be "named," although the terms "constant" and "named constant" are often used interchangeably". I'd prefer "cannot be altered" over "should not be altered" because that implies you do dirty stuff like "self modifying code". Furthermore, the definition doesn't address values that are the result of "constant folding" (which means they can be resolved at compile time). There has been quite some discussion on the ontology of C - and I think the consensus is (please correct me if I misunderstood) that SOME macros can effectively result in a constant, but that true constants (which are determined at compile time and inlined when used) don't actually exist in C. E.g. #define TEN 10 #define ONE 1 #define ELEVEN (ONE+TEN) int main (void) { int MyArray[ELEVEN]; MyArray[0] = TEN; } But is preprocessed to: int main (void) { int MyArray[(1 +10)]; MyArray[0] = 10; } Which means the compiler has to do *some* kind of constant folding to size "MyArray".
@thediaclub4781
@thediaclub4781 Жыл бұрын
I tested the pointer thing in c++ and I got different values at the same address. Code used: int main() { const int a = 42; int* p = (int*) &a; *p = 69; std::cout
@SpeedFlap
@SpeedFlap Жыл бұрын
That happens probably due to compiler doing optimizations. Read access to a is replaced by using the initial value of a which is still in a register, since a is a local variable and was previously initialized. It isn't aware that the value was modified behind its back. Try making a volatile.
@thediaclub4781
@thediaclub4781 Жыл бұрын
​@@SpeedFlap This actually worked. I didn't expect that something "volatile const" exists. But now it makes some sense for me since const means read-only.
@SpeedFlap
@SpeedFlap Жыл бұрын
@@thediaclub4781 In common sense volatile const is meaningless. But actually, volatile here means "don't optimize, because value could change". So it makes the pointer hack work. That is so counter intuitive. C can be frustrating...
@maxaafbackname5562
@maxaafbackname5562 7 ай бұрын
​@@SpeedFlapthe const keyword makes the variable read-only. By default a variable is assumed constant, the volatile keyword removes this constant situation.
@InspektorDreyfus
@InspektorDreyfus Жыл бұрын
And what exactly is an 'integer constant' that the switch wants to have? Should the error message instead say 'integer literal' to be more clear?
@HansBezemer
@HansBezemer Жыл бұрын
Try *any* natural number within the 32bit or 64bit range - because that's what it boils down to when preprocessed.
@scottfranco1962
@scottfranco1962 Жыл бұрын
Same reason const int a; const int b = a+1; didn't used to work. a is not really a constant, its a variable with a property. The compiler has to do extra work to figure out that a actually can be treated as a constant, and it used to not do that but now does. So in the future we can expect case a: ... to work. What that boils down to is the compiler has to make a lot of exceptions to get things to work.
@HansBezemer
@HansBezemer Жыл бұрын
@@scottfranco1962 .. and that's exactly why I don't like it. There is such a thing like "consistent design". Or to paraphrase a famous quote ""You compiler boys were so preoccupied with whether you could, you didn't stop to think if you should."
@scottfranco1962
@scottfranco1962 Жыл бұрын
@@HansBezemer I didn't design C, but I do design compilers and languages. If I made a list of design problems with C, it would be a book (and in fact many such books have been written). So first of all, you came to this party (C), instead of selecting a better language. So strike one. So why this mess with constants? Because C has constants and constant expressions, but never had a constant DECLARATION (as, indeed, other languages do). I would assume they skipped that because it was easy to do with macros, and the goal of C was to keep things simple (the original C, not the nightmare of C++). Why were macros a deal in C? Again speculation, but at the time C came about, Fortran was the dominant language, and macroprocessors were a thing (Ratfor). So to keep C simple, lots of things got shoved off on the macroprocessor. Constants are one, but so was file inclusion, and (as many have argued) the entire modularity scheme of C.
@HansBezemer
@HansBezemer Жыл бұрын
​@@scottfranco1962 Nobody in his right mind would say that C hasn't got any design errors. Dennis Ritchie would be the first one to agree. And I usually prefer to write in Forth. However, IMHO there is NOTHING that remotely touches C when system software is concerned (Forth like to BE the operating system - it's not geared to MAKE an operating system). C is the result of a pragmatic design - like the mess that PHP and Perl are as a result of pragmatic design. Those are usually not the most elegant, beautiful languages. The point that we've come to love C comes from its utter simplicity (it doesn't try to be overly smart) and its proven usability. I have written non-trivial programs that compile under a vast host of compilers (even K&R) and are still compact and run VERY fast. I can't see any other (compiled) language match that feat. It shares the same characteristics with Unix - you asked for it, now you got it. In its inception it didn't try to be overly smart. I think its reputation as "high level assembly" is deserved. I think C's modularity (lots of functions in libs instead of "built in", pushing much responsibility to the preprocessor) is in itself defensible as a design choice. It keeps the core compiler small. You may discuss the lack of defining true constants in the core language (as you probably know, that's not hard to do) and I will certainly agree to the possible problems that this poses in C when a substitution doesn't turn out to be quite what you expected, but I wouldn't consider it to be completely INdefensible or unworkable. So, yes, I largely agree with your comment, but I'm a bit more nuanced here. Would "my" C have been different? Most certainly. It would be even more stupid (that's why I like Forth - even no type checking). Would I trade C for another language? I suppose so - but IMHO nothing comes near. There is a tendency towards ever more "clever" languages, that always seem to get in my way when I wanna do things. That even happens with more modern C compilers. I can't say it's a direction I particularly like.
@johnshaw6702
@johnshaw6702 2 ай бұрын
I'll come back, but apparently I've been programing to long. Obviously they are not the same, although the enviroment they are in makes a difference as to whether you can mess with them. I basically failed an interview some years ago because i said const and some other syntax were promises the compiler inforced. I should have pointed out that the promise could be cercumvented. They apparently thought they were set in concrete.
@tomaszstanislawski457
@tomaszstanislawski457 Жыл бұрын
`enum { A = 10, B = A + 1 };` will work perfectly fine
@annie3606
@annie3606 Жыл бұрын
Mentioning C++ people I would more mention the fact that in C++ this is more clear, due to the fact that you can take const params to indicate that you do intent on using that value readonly, then the fact that C++ has tools for compiletime constants
@Minty_Meeo
@Minty_Meeo Жыл бұрын
And this is why constexpr was added to C++. Edit: It's me. I'm C++ people.
@lennymclennington
@lennymclennington Жыл бұрын
EDIT: I just saw the latest video does mention enums but didn't really show the differences much. Original comment: I'm surprised enums weren't mentioned in this video considering those are an actual way of having a numerical constant which isn't just using preprocessor text replacement to fake it, so the compiler can actually tell which context the enumeration's name refers to the constant and which context it's not being used as a constant. e.g. you can have enum { A = 10 }; And still declare a struct or union or typename called A e.g. "struct A;" (whereas if you use a macro then "struct A;" would just be replaced with "struct 10;" which is not valid)... Although maybe it's not the best idea to have those things all called A in the first place, but still it can be done, and I feel like it would've been worth mentioning in this topic. Also, constexpr was briefly mentioned in the end, but no mention that constexpr is being added to C in the upcoming C23 standard.
@boristheengineer5160
@boristheengineer5160 6 ай бұрын
maybe we should just add "#define immut const" then instead of const we could declare an "immut int" since "immutable" is understood as something that WE aren't allowed to change. This reminds me of a recurring embedded problem where a microcontroller's hardware allows writing to the input port which has the same effect as writing to the output latch but allows for some tricky read-modify-write bugs. In my opinion the input port should be declared "const volatile".
@tonyguillot4998
@tonyguillot4998 Жыл бұрын
This video makes me remember that Clang is working on improving constexpr and constexpr in C23
@codytubbs
@codytubbs Жыл бұрын
even a side-note on differences with Clang and the switch/case A && B example from the video -- compiles just fine. :shrug:
@ABaumstumpf
@ABaumstumpf Жыл бұрын
Most of what he said is not actually correct. there is no such thing as "a constant" in C.
@paulc2448
@paulc2448 Жыл бұрын
That's why i code in C, with a C++ compiler. And thx for the video, i see that my C is rusty. I wasn't aware that dynamic array size (MyArray[A] local variable) was in the C standard ^^', that would be useful in c++ instead of relying on alloca... (or platform specific stuff....)
@sleepntsheep1169
@sleepntsheep1169 Жыл бұрын
even in C++, most compiler support VLA so if you really need stack allocation just use VLA
@paulc2448
@paulc2448 Жыл бұрын
If it doesn't compile, it doesn't haha... (Visual Studio 2019) i was amazed that the customized g++ provided with the ps3 sdk was able to do that (several years ago indeed).
@hwstar9416
@hwstar9416 5 ай бұрын
C23 will add `constexpr` fixing the issues you mentioned
@vaibhavsingh-fu1vg
@vaibhavsingh-fu1vg 3 ай бұрын
It seems that from C99 onwards this is valid? clang had no issues with it during compilation? const int a = 10; int abc[a]; int main(void) { return 0; }
@amekudzilab
@amekudzilab Жыл бұрын
Insightful 💡
@martiananomaly
@martiananomaly Жыл бұрын
intsightful 😁
@JacobSorber
@JacobSorber Жыл бұрын
😂
@ABaumstumpf
@ABaumstumpf Жыл бұрын
Sadly oh so wrong.
@flippert0
@flippert0 7 ай бұрын
"C": when it walks like a const, and talks like a const, it's still not a const.
@SianaGearz
@SianaGearz Жыл бұрын
It's also relevant when you're doing embedded dev and you have a microcontroller with maybe 32kib ROM space (abundant) but only 1kib RAM (scarce), so your variables end up eating into your scarce resource. Then unfortunately every compiler has to come up with its own nonstandard way to declare truly constant constants which are actually in ROM and don't get maintained in RAM.
@toddblackmon
@toddblackmon Жыл бұрын
In general, embedded compilers will place const variables into the ROM space. It's very useful to create large const data structures. No nonstandard features are needed. Check your linker script to see why it might not be doing that.
@SianaGearz
@SianaGearz Жыл бұрын
@@toddblackmon On ARM that is supposed to work, since everything is in the address space. On AVR, a pointer to ROM cannot be taken, it cannot exist, different instructions are used to access ROM and RAM, and same numerical values of address will refer to different locations. So avr-gcc has you declare ROM constants with PROGMEM attribute and access them with functions from pgmspace.h.
@toddblackmon
@toddblackmon Жыл бұрын
@@SianaGearz Interesting. Luckily that kind of silliness is becoming less common since modern processors are designed with compilers in mind.
@parthbansal2775
@parthbansal2775 Жыл бұрын
Not to state the obvious but a const int will be a constint and not a constant. I will see myself out
@neotune64
@neotune64 Жыл бұрын
So what should I use then if I want to declare a constant in C?
@v01d_r34l1ty
@v01d_r34l1ty Жыл бұрын
By definition, a constant is just a value that doesn’t change. Take that as you will.
@ABaumstumpf
@ABaumstumpf Жыл бұрын
In C there is no such thing as "a constant". "const int A = 10;" defines a constant integer with the value 10 and the identifier 'A'. This is a value that can not change (contrary to his claims). But this can not be used for say switch-statements cause those require a "constant expression" - which is different from a constant value. "1" is a constant expression, same as "6+5/3" is. Also enums are constant expression. So if you want to be able to switch on a number that you give a name - that is what enums are for - they are "integer constant expression" hence can be used anywhere C requires a constant expression. "#define A 10" is NOT "a constant" (again there is no such thing). Why? Cause defines are not C-code but instructions for the pre-processor to go through the entire document and search-and-replace every occurrence of 'A' and replace it by the number 10 - and that integer-literal is then a constant expression.
@kreuner11
@kreuner11 Жыл бұрын
You can probably force type checking on a macro by doing ((int)10), then it'll tell you about any implicit cast with the right warning flag
@czarsonxd2093
@czarsonxd2093 Жыл бұрын
a plain `10` is of type int, no need for the cast
@kreuner11
@kreuner11 Жыл бұрын
@@czarsonxd2093 yeah, but it when you pass it to another type it will tell you at that point
@MECHANISMUS
@MECHANISMUS Жыл бұрын
Didn't get the problem of switch. Why shouldn't it work?
@ABaumstumpf
@ABaumstumpf Жыл бұрын
Cause nothing he said is really correct. the "case" requires a "constant expression" and a "const int" is constant, but not a constant expression. There just is no such thing as "a constant" in C.
@yosef5508
@yosef5508 Жыл бұрын
Excellent video, but the four constant types in C are worth reviewing.
@jorgeferreira6727
@jorgeferreira6727 Жыл бұрын
How about "#define A ((int)10)" in order to have some type check?
@monochromeart7311
@monochromeart7311 Жыл бұрын
10 is implicitly an int already. 10. or 10.0 would implicitly be doubles.
@jorgeferreira6727
@jorgeferreira6727 Жыл бұрын
@@monochromeart7311 I know that. But, for some compilers at least, adding an explicit type cast can trigger extra semantic validation.
@monochromeart7311
@monochromeart7311 Жыл бұрын
@@jorgeferreira6727 if that includes gcc and clang, then thanks for the info!
@jorgeferreira6727
@jorgeferreira6727 Жыл бұрын
@@monochromeart7311 Not sure about those. In 30 years, I have used lots of different compilers, both for desktop and embedded systems. The ones for embedded systems tendo to have lots of hardware specific extras, and I may be mixing concepts from a specific compiler. Its better try it, or as I do, make sure to don't leave too much guess work for the compiler. Its like using extra parenthesis, even when the operators precedence makes them unnecessary, just to make complex expressions absolutely clear to me and anyone who reads my code.
@monochromeart7311
@monochromeart7311 Жыл бұрын
@@jorgeferreira6727 you have good points, I will also start adding those casts.
@z08840
@z08840 Жыл бұрын
const variables placement is implementation defined - it can be allocated in read-only section - don't write to it - it will end badly eventually
@StefanNoack
@StefanNoack Жыл бұрын
BUS ERROR
@raptoress6131
@raptoress6131 Жыл бұрын
"A const int in C is not a constant." Lol got it
@ABaumstumpf
@ABaumstumpf Жыл бұрын
Sadly the video is just wrong about most things.
@WouterStudioHD
@WouterStudioHD Жыл бұрын
C23 gets constexpr
@gdotone1
@gdotone1 3 күн бұрын
the thing to do here is to fix this in the compiler
@trevortrevose9124
@trevortrevose9124 Жыл бұрын
Can you do a video about consexpr
@90_98
@90_98 8 ай бұрын
That's why C23 which adds constexpr is so great
@maxaafbackname5562
@maxaafbackname5562 7 ай бұрын
That's the same constexpr as from C++11?
@shriram5494
@shriram5494 Жыл бұрын
So basically by constant you mean only rvalues?
@_CazaBobos
@_CazaBobos Жыл бұрын
I know they use the same compiler, but isn't "bool" a c++ specific datatype like "string"?
@TranscendentBen
@TranscendentBen Жыл бұрын
Yes and no! bool is a built-in c++ type just as int is. string is a class and is part of the STL. I recall that C99 (the big standard version that has most everything useful in C) has a IIRC stdbool.h header you can include that defines, bool and true and false, but they're not fundamental.
@ivanscottw
@ivanscottw Жыл бұрын
defining const int A = 10; assigns storage because it has external linkage. If you were to instead static const int A = 10; And never reference to it by address in your code within the scope of the file and compile with optimization, this will NEVER occupy any storage area.
@didiTchu
@didiTchu Жыл бұрын
why dont you use clion?
@mikefochtman7164
@mikefochtman7164 Жыл бұрын
If you need an int constant with type checking, you can try 'enum'. Usually we think of that as a range of some enumerated type, but you can have an 'enum' type with one element, assigned the value you would like. i.e. "enum ArraySizing(Size=10);" I believe this will get past some of the shortcomings you mention. Of course in C++ there's a class for it, but the enum datatype in C is pretty useful for a lot of these sorts of things.
@redcrafterlppa303
@redcrafterlppa303 Жыл бұрын
I don't get why you can't use a read-only variable as a condition. The same code exploded to if-else works fine. Sure the compiler might not be able to optimize is as well as if they were literals. But this feels like an unnecessary language restriction. Edit : Switched on - > use.. as a condition
@johnheaney3349
@johnheaney3349 Жыл бұрын
If you define a const variable in the body of the function as a local or auto then there can only be one path through the switch statement, which would negate the purpose of the switch statement. You can certainly switch on a const parameter to a function.
@HansBezemer
@HansBezemer Жыл бұрын
You can use a "const integer" as long as you put it in the switch() statement: #include const int x; int main (void) { switch (x) { case 0: printf ("It is zero "); break; case 1: printf ("It is one "); break; default: printf ("It is something else "); break; } } No, it doesn't even generate an error. Yes, it executes. And no, it doesn't display "It's something else".
@redcrafterlppa303
@redcrafterlppa303 Жыл бұрын
@@HansBezemer I'm talking about a const int being used as a condition not as the input for the switch. Just like shown in the video.
@HansBezemer
@HansBezemer Жыл бұрын
BTW, not all compilers always compile a switch() statement to an "if else if else if" statement. Some compile it (under certain conditions) to a jumptable - which can REALLY speed up your code, since it only has to calculate the offset and then just perform a jump. If there is a "hole" before your range, it can "clip" the value to a minimal value. Same for a "hole" at the end of the range.
@HansBezemer
@HansBezemer Жыл бұрын
@@redcrafterlppa303 I know what he's shown. He's shown a read-only variable is not the same as a literal integer. For obvious reasons you can't use variables in case-statements. Seems quite clear to me. I find it quite surprising that an expression like MyArray[A] even compiles. If I wrote a C compiler, I wouldn't allow it. It's plain ridiculous IMHO. The current generation of C compiler designers - well, let's put it this way: there goes the neighborhood.. Or do you find this sane behavior for a C compiler? Do you have any idea what is actually written here? #include const int x; int main (void) { int MyArray[x]; printf ("%d ", x); printf ("I'm using it!! %d ", MyArray[0]); } It compiles without errors or warnings..
@nandanvasudevan
@nandanvasudevan Жыл бұрын
7:51 I do prefer enum (better would be enum classes) inside a switch...
@euchre90
@euchre90 Жыл бұрын
Indeed, that was a bit of a misuse of a switch case... Made more sense to do something simple like return (value == A || value == B); or go bitwise if you really want to avoid branching code
@corscheid
@corscheid Жыл бұрын
48 things on Git @_@ My 0-notification anxiety is on fire
@leo940806
@leo940806 5 ай бұрын
I am not a hardcore C programmer. I write C for MCU firmware development. I have never used "const" and don't know what is the use of it. If I need something constant I rather use Macro. Can anyone show me when will you use const instead of macro?
@BigYoshi826
@BigYoshi826 Жыл бұрын
You didn't tell us what DOES create a constant
@edgeeffect
@edgeeffect Жыл бұрын
Using a different programming language?
@monochromeart7311
@monochromeart7311 Жыл бұрын
enums. enum MyEnum /* MyEnum is now a new type */ { A = 10, B, /* implicitly equals to A+1 */ }; bool isAorB(enum MyEnum num) { switch(num) { case A: case B: return true; } return false; }
@anon_y_mousse
@anon_y_mousse Жыл бұрын
@@edgeeffect Funny, but still a bad answer. C is all you need.
@ABaumstumpf
@ABaumstumpf Жыл бұрын
Simple: NOTHING: C does not have a thing that is "a constant"... sadly most of his assertions in this video are wrong. "const int A = 10;" does define a constant integer. Simpel as that. But things like initialising a const-int requires a constant EXPRESSION and that is just something different. Any literal is a constant expression - so "34634" is, or "10+5*2" is also a constant expression. If you want to have a name for a specific value - that is what enums are for. Also with 'define' you do not get constants cause defines are just simple string-replacements. The compiler NEVER sees them. When you use "#define A 10" all that this does is that before the compiler gets the source it scans the files and replaces every single occurrence of 'A' with whatever string you gave it - in that case '1' - so an integer literal. (also no, contrary to his claims it is not possible to change the value of 'A' as that was declared as being const)
@monochromeart7311
@monochromeart7311 Жыл бұрын
@@ABaumstumpf enums are constant. Also, C23 has constexpr to make things compile-time constant.
@TheBrainDunne
@TheBrainDunne Жыл бұрын
aren't these just scope issues because you are creating the array and switch function in file scope where it is not determined that the const int is initialized yet.
@TheBrainDunne
@TheBrainDunne Жыл бұрын
ok, I see. use enum for constants then
@cyrilanisimov
@cyrilanisimov Жыл бұрын
What about "static const int"?
@HansBezemer
@HansBezemer Жыл бұрын
If it's in a module, its name isn't exported. That's all.
@cyrilanisimov
@cyrilanisimov Жыл бұрын
@@HansBezemer it should initialized on startup and store in static memory space
@HansBezemer
@HansBezemer Жыл бұрын
@@cyrilanisimov Not if it's a global.
@TheRobbix1206
@TheRobbix1206 Жыл бұрын
@@cyrilanisimov It should be initialized BEFORE startup, that's why most compiler put static const under a readonly section of your program. So it is not really initialized like setting it's value by hand, but rather by just putting the corresponding space of your program to the address required by the program.
@scottfranco1962
@scottfranco1962 Жыл бұрын
Yea, I tried to use const to get around declaring macros, and rapidly ran into issues. I gave it up. Its too bad.
@sophiacristina
@sophiacristina Жыл бұрын
And waste of bytes... :p
@scottfranco1962
@scottfranco1962 Жыл бұрын
@@sophiacristina Why? I would presume the compiler is smart enough not to allocate it.
@sophiacristina
@sophiacristina Жыл бұрын
​@@scottfranco1962 tbh, i don't know how far compilers works with that, but, by what i learned, not. I'm not a pro, someone correct me if i'm wrong. But... It happens because when you declare a const, that is like saying to the compiler "i WANT a space in the memory". The compiler would think "if you have not used macro, so you want a space in the memory" (it wasn't pre-processed), this happens because a const int (or type) can be accessed with pointers and reference, while a macro can't. This can't work without memory space, if the compiler is smart enough to notice if you never used pointers / reference, i'm too lay to know, and then, sorry for that. A const is just like any type, but the value can't be changed, but it acts like an variable. That is why "a const is not a const", because it is basically a non-modifiable variable. Sounds confusing, don't? Summarizing, you are telling the compiler that you need something that can also be accessed by the memory location...
@scottfranco1962
@scottfranco1962 Жыл бұрын
@@sophiacristina Naw, modern compilers are capable of removing unused variables. A const int that never gets referenced as a runtime variable would be eliminated. It has a value at compile time because it is immutable, and not having a runtime reference would flush it out. As someone else mentioned, this is distinct from #define, because #undef can change the value of it in regions of the file.
@sophiacristina
@sophiacristina Жыл бұрын
@@scottfranco1962 interesting to know... Ty! :)
@justengineering1008
@justengineering1008 Жыл бұрын
maybe, we should not mix up maths terms and C terms🤔
@dixztube
@dixztube Жыл бұрын
Malloc shirt. Bruh lmao I love it
@KangJangkrik
@KangJangkrik Жыл бұрын
For other embedded system developers: DO NOT use #define with strings, or the memory usage would be bloated
Жыл бұрын
And this behavior is compiler dependent. Modern compilers can perform optimization for case like that and allocate storage once. Some linkers can do same job for duplicated symbols across different modules. For same reason const can be a real constant, there are plenty different platforms with different architectures, compilers, operating systems and hardware extensions, even present x86 can use memory protection to avoid changing application code at runtime.
@KangJangkrik
@KangJangkrik Жыл бұрын
@ unfortunately, Arduino IDE won't do this modern optimization. I tested myself and this problem was validated
Жыл бұрын
@@KangJangkrik, can you give any example? In single file I can't reproduce this behavior, I can use many times same literal with macro as function argument, assigning it to different const, etc. And program size doesn't change at all when I use string literal once and when I use it many times. Arduino use GCC and GCC performs well for optimizations like this, it has even option to do same optimization at link time (merge-constants).
@KangJangkrik
@KangJangkrik Жыл бұрын
@ which board you're using? I just tried it and seems like the problem was fixed in Arduino Uno but still apparent on STM32
@cellularmitosis2
@cellularmitosis2 Жыл бұрын
So why hasn’t gcc fixed this yet?
@justian428
@justian428 Жыл бұрын
I'm very confused. Maybe you should have started by stating what "constant" means, and why a const int is not a constant... Can anyone explain to me?
@mk72v2oq
@mk72v2oq Жыл бұрын
Because its in fact is a read-only variable. To understand the difference you should code in any language that have both concepts. Like C# where you can use both 'const int x' (will be a true constant, by behavior its closer to #define macro in C) and 'static readonly int x' (effectively works similar to C const).
@robheusd
@robheusd Жыл бұрын
A constant is not a constant, at least not at sea. But perhaps at land it is?
@Voltra_
@Voltra_ Жыл бұрын
good old enum trick
@teslainvestah5003
@teslainvestah5003 Жыл бұрын
of course not. in order to make an const int into a constant, you have to solve for its mother's sister. its constaunt. She runs a restaurant with a lot of drawbacks - mainly that she employs only escaped serial killers for cooks and pirates for waiters. The eggs and the toast escape unscathed. So they don't sell well. When we go there, we never get that bread. And when the police come by for coffee, the waiters all make like the eggs and rum.
@georgecop9538
@georgecop9538 Жыл бұрын
I can say I switched from C to HolyC (and TempleOS). Would you do an episode on that?
@Hellohiq10
@Hellohiq10 Жыл бұрын
Legend
@user-he4ef9br7z
@user-he4ef9br7z Жыл бұрын
You'd have to always be in a TempleOS Virtual Machine. There's no way to run it on other OSs, otherwise I'd have switched too. On top of that it's JIT compiled. So I think it's slower.
@anon_y_mousse
@anon_y_mousse Жыл бұрын
@@user-he4ef9br7z It compiles things before it runs them, but it does it really fast, even through a VM.
@cerulity32k
@cerulity32k Жыл бұрын
*(int*)A=100;
@michmart9261
@michmart9261 Жыл бұрын
You had one job!
@PvblivsAelivs
@PvblivsAelivs Жыл бұрын
It's a very simple rule: If it exists in memory, it is not a constant. There is a similar problem with "null" pointers. Address 0 exists.
@GrzesiuG44
@GrzesiuG44 Жыл бұрын
This is true in practice, but is also dangerous to use. Even if your machine has address 0 it is invalid to represent it as null pointer. And with constants - i believe if your code can observe change of a constant, it can do so only via undefined behavior.
@maxaafbackname5562
@maxaafbackname5562 Жыл бұрын
Define "memory". ROM is (also) memory.
@justwatching6118
@justwatching6118 Жыл бұрын
In C# you have readonly and const..
@anon_y_mousse
@anon_y_mousse Жыл бұрын
Yet more reason to hate C#. It would've been super easy to just change the behavior of const, it was a new language once, or even to excise the keyword to avoid confusion with C and C++, but instead they leave it and add extra keywords and at that two word keywords. It makes me sad that it just won't die as a language.
@typedef_
@typedef_ Жыл бұрын
@@anon_y_mousse C# is a superb programming language in every aspect.
@anon_y_mousse
@anon_y_mousse Жыл бұрын
@SlowSunsetVibes It does affect me, though. I'm far too often forced to use it. It's a garbage language that only exists because Sun wouldn't bend over and do whatever Microsoft wanted. Only makes it worse that Java was a garbage language already and C# degraded the quality from there.
@portblock
@portblock Жыл бұрын
I do like your videos, however, if I may, and not to challenge, just a different point of view, all this depends on the environment. I see a lot of your videos that sometimes dont make sense to me, then I am like, oh, linux type of compile. Example, in this video, const does mean constant to me, and constant to me means a variable in ROM not in ram. I was an embedded engineer (still part time) and const int | long, means the the bytes will be allocated in rom space and they are constant, constantly holding their values. semantics? maybe, but again point of view and environment/platform. "not a constant" depends on what you are perceive constant to be. In my arena every programmer I know (embedded) know that const = constant (as we perceive the word) - all in all, not saying you are wrong, just saying lack of context makes this confusing. I know you are a teacher and that is great, but please add context
@thomassynths
@thomassynths Жыл бұрын
FWIW: `#define A ((SomeIntTypedef)1)`
@UrSoMeanBoss
@UrSoMeanBoss Жыл бұрын
As a pedantic asshole, I find this video quite troubling.... But I guess from a layman's point of view, it's informative. Fine. BUT!! regarding the modification of a const-qualified variable via pointer arithmetic, you should be VERY careful to explain that it's undefined behavior in the eyes on the language. That may require a slightly deeper discussion about the language specification and how it views specified/unspecified/impl. defined/undefined, and how all those boil down to conceptual "guarantees" (whether the language, the platform, the implementation, or dumb luck is guaranteeing the behavioral correctness of your program)
@bachvaroff
@bachvaroff Жыл бұрын
enum { A = 10 }; /* good enough, int only */
@pow9606
@pow9606 Жыл бұрын
The Array creation and the switch statement compile just fine. Even with Warning level set to maximum of 4. I was slightly unsure about the array creation but after thinking about it, I expect it to compile fine. The A and B variables are created by the time the compiler gets to the array creation statement. The switch statement should never be a problem because the const variable is just being compared. A const variable cannot be assigned to unless by pointer or recasting away the const. I suggest you check your compiler and change to a compiler version that works properly.
@bamberghh1691
@bamberghh1691 Жыл бұрын
What compiler are you using?
@simonrazer8303
@simonrazer8303 Жыл бұрын
You did not actually explain what makes a constant constant now. You just showed that it is not the same as #define. And const int ist still read only, so any sane person wont change it. I hope you make a video properly explaining the difference.
@AV_YOUTUBE_202X
@AV_YOUTUBE_202X Жыл бұрын
_Good ole C_
@pierreabbat6157
@pierreabbat6157 Жыл бұрын
const int anople=330;
@sanderbos4243
@sanderbos4243 Жыл бұрын
4:28 you say "Because we can get the address, we could use pointer tricks to actually change the value of A. Let me know if you'd like to see that in a future video. It's not something you would normally want to do, but of course that hasn't stopped us in the past, and most of our compilers actually let us do it even if it doesn't make any sense." I think a lot of people could use a video on why casting a const away and then writing to it is Undefined Behavior, and what UB is in general, showing off examples.
@sanderbos4243
@sanderbos4243 Жыл бұрын
If on StackOverflow you look up "Is it Undefined Behaviour to cast away the constness of a function parameter?" you will find further discussion of this topic, including a very special case in which it is defined behavior to cast a const away and to then write to it.
@TheRobbix1206
@TheRobbix1206 Жыл бұрын
@@sanderbos4243 I don't see any defined behaviour on the stack overflow post, just that it is used for strstr, but as strstr is implementation defined this is not a problem
@sanderbos4243
@sanderbos4243 Жыл бұрын
@@TheRobbix1206 "But if the caller passes you a pointer to data that in fact is mutable, then behavior is defined. Creating a const char* that points to a modifiable char doesn't make that char immutable." from the accepted answer on that post. I really like the first comment under that as well: "(im)mutability is an inherent property of the object itself, regardless of the qualification of the pointer used to access it"
@rmaster934
@rmaster934 Жыл бұрын
@@sanderbos4243 yeah, iirc, you can 'safely' remove const away if the object is not living in 'read-only' memory; bascially all global/static consts, string literals.
@ABaumstumpf
@ABaumstumpf Жыл бұрын
​@@rmaster934 No. You can ALWAYS safely "remove" the const, but you can ONLY safely manipulate the object if the object it self is not const. Aka "const int A = 10; int *ptrA = &A; -- non-const pointer is well defined and allowed printf("ptrA=%p *ptrA=%d", (void*)ptrA, *ptrA); // *ptrA = 2; changing the object would be undefined behaviour "
@DeveloVooshGWeb
@DeveloVooshGWeb Жыл бұрын
it's not a const ant it's a const int
@Rai_Te
@Rai_Te 3 ай бұрын
Who needs constants?
@Littlefighter1911
@Littlefighter1911 Жыл бұрын
4:33 you could not. Try it, in a future video. It's a constant. The compiler treats the const as constant and will replace the value as if it was a literal, but otherwise check the syntax as if it was of that type (even if it allocates a sizeof(int) big variable in .rodata and therefor has a pointer to it). That's the point of using const. It doesn't matter, if you replaced the value that it points to, as long as it's not been passed as a pointer into a function, that has not been inlined by the compiler. Stop spreading misinformation by the lack of testing and assuming. Just compile your example with -S and look at the output. If you don't use your "&A" but "A" and use "%d" for formatting, you will see it pushing the value "10" on stack (or to the appropriate registers), regardless of if you change it afterwards. To be more precise, you can't even cast away the const, as the section it will land in will be read-only on most systems and therefor crash if you try rewriting it. Thus it's a constant, yeah it might not be able to be picked up by the pre-processor at all times, but it's still a constant. 8:23 That's not valid. You can't use ints in a case. That's not how C works. It's still a constant. It's not a integer literal. But if you were to call it that, the title wouldn't have been clickbaity enough.... What you did, is redefining what a constant is in C and then say it's not constant, for your 9 minute video of internet spew. Just as Pannenkoeck with his BS excuse of introducing the term half-button-press and parallel universe. Some people seem to celebrate this internet spew...
@gloverelaxis
@gloverelaxis Жыл бұрын
it is such a disgrace that the only serious open operating system in the world is written in this language
@kermitdafrog8
@kermitdafrog8 Жыл бұрын
Why is it a disgrace? What's wrong with the language?
@user-he4ef9br7z
@user-he4ef9br7z Жыл бұрын
C is the best programming language. And there are plenty open operating systems, some them are not written in C.
@casperes0912
@casperes0912 Жыл бұрын
There's a proposal to do some parts of Linux in Rust. But what did you have in mind? Pretty much all operating systems ever are composed of C + Assembly.
@MrBeanbones
@MrBeanbones Жыл бұрын
C is the best language, mother of the most of the other languages
@monochromeart7311
@monochromeart7311 Жыл бұрын
@@kermitdafrog8 I'm also interested to know.
@captainfordo1
@captainfordo1 Жыл бұрын
C23 is getting constexpr.
Understanding the For Loop (examples in C)
18:37
Jacob Sorber
Рет қаралды 16 М.
Clarifying about literals, macros, and const (still not constant?)
13:14
Who has won ?? 😀 #shortvideo #lizzyisaeva
00:24
Lizzy Isaeva
Рет қаралды 7 МЛН
Vivaan  Tanya once again pranked Papa 🤣😇🤣
00:10
seema lamba
Рет қаралды 32 МЛН
Nutella bro sis family Challenge 😋
00:31
Mr. Clabik
Рет қаралды 11 МЛН
When do I use a union in C or C++, instead of a struct?
11:18
Jacob Sorber
Рет қаралды 67 М.
Should I pass by const reference or by value?
10:45
The Cherno
Рет қаралды 99 М.
2 Years Of Learning C | Prime Reacts
22:24
ThePrimeTime
Рет қаралды 250 М.
Defining Constants. Should I use CONST or #DEFINE?
7:59
Jacob Sorber
Рет қаралды 55 М.
The Most Useless Keyword in C?
10:26
Jacob Sorber
Рет қаралды 68 М.
`const` was a mistake
31:50
Theo - t3․gg
Рет қаралды 126 М.
WHY IS THE STACK SO FAST?
13:46
Core Dumped
Рет қаралды 140 М.
Pulling Back the Curtain on the Heap
21:38
Jacob Sorber
Рет қаралды 36 М.
The ONLY C keyword with no C++ equivalent
13:17
mCoding
Рет қаралды 266 М.
What's the Best Way to Copy a Struct in C and C++?
13:44
Jacob Sorber
Рет қаралды 33 М.
Who has won ?? 😀 #shortvideo #lizzyisaeva
00:24
Lizzy Isaeva
Рет қаралды 7 МЛН