A const int is not a constant.

  Рет қаралды 69,542

Jacob Sorber

Jacob Sorber

Күн бұрын

Пікірлер: 351
@johnheaney3349
@johnheaney3349 2 жыл бұрын
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 2 жыл бұрын
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 2 жыл бұрын
Thanks for cleaning up the ontology of C used here. I recently did a KZbin 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 2 жыл бұрын
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 2 жыл бұрын
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 2 жыл бұрын
@@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 2 жыл бұрын
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 2 жыл бұрын
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 2 жыл бұрын
Me: **removes exception from PhysicsEngine* Problem solved :)
@tk36_real
@tk36_real 2 жыл бұрын
"differences in use of volatile, const" - there are none, they are syntactically equivalent
@paulc2448
@paulc2448 2 жыл бұрын
label 'language' was undefined.
@dangnabbit1379
@dangnabbit1379 2 жыл бұрын
Weird use of object notation but ok
@eddiebreeg3885
@eddiebreeg3885 2 жыл бұрын
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 2 жыл бұрын
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 2 жыл бұрын
@@_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 2 жыл бұрын
@@eddiebreeg3885 yes
@ABaumstumpf
@ABaumstumpf 2 жыл бұрын
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 2 жыл бұрын
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 2 жыл бұрын
@@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 2 жыл бұрын
"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.
@xarcaz
@xarcaz 2 жыл бұрын
It IS a constant. Just not a compile-time constant (such as pre-processor defines, enum values, and C++ constexpr values).
@reinhold1616
@reinhold1616 2 жыл бұрын
pre processor defines are not compile time :)
@xarcaz
@xarcaz 2 жыл бұрын
@@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 2 жыл бұрын
@@xarcaz i meant that defines are evaluated by the pre processor which runs before the compiler
@xarcaz
@xarcaz 2 жыл бұрын
@@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 2 жыл бұрын
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 2 жыл бұрын
Does this give a performance boost?
@harrytsang1501
@harrytsang1501 2 жыл бұрын
@@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 10 ай бұрын
@@jftsang on microcontrollers there is a limited RAM, while program and const data is usually stored in a ROM.
@xcoder1122
@xcoder1122 10 ай бұрын
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 7 ай бұрын
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 жыл бұрын
2:17 You can #undef and then redefine with a new value. It's not really a constant, just a macro
@HansBezemer
@HansBezemer 2 жыл бұрын
When preprocessed it is a literal. Believe me.
@johnheaney3349
@johnheaney3349 2 жыл бұрын
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 2 жыл бұрын
@@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 2 жыл бұрын
@@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 2 жыл бұрын
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.
@Siger5019
@Siger5019 2 жыл бұрын
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 2 жыл бұрын
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 2 жыл бұрын
@@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 2 жыл бұрын
@@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 2 жыл бұрын
​@@Minty_Meeo Oh yeah so a literal character won't ever use the whole 64 bits. That make sense.
@0LoneTech
@0LoneTech 2 жыл бұрын
I've literally fixed bugs changing 1
@parthbansal2775
@parthbansal2775 2 жыл бұрын
Not to state the obvious but a const int will be a constint and not a constant. I will see myself out
@adecy9669
@adecy9669 2 жыл бұрын
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 Жыл бұрын
Wait, why is that funnier? 🤔
@nicholaswood3250
@nicholaswood3250 2 жыл бұрын
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 2 жыл бұрын
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 2 жыл бұрын
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 2 жыл бұрын
@@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 2 жыл бұрын
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 2 жыл бұрын
@@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 2 жыл бұрын
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.
@maxaafbackname5562
@maxaafbackname5562 2 жыл бұрын
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 2 жыл бұрын
True. It's a "read only integer variable". If you want a true literal, you use #define. K&R was right.
@donjonmaister
@donjonmaister 2 жыл бұрын
I was about to comment that, but you beat me to it. Yes, you are absolutely right 😁👍
@sb_dunk
@sb_dunk 2 жыл бұрын
@@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
@HinaraT
@HinaraT 2 жыл бұрын
@@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 2 жыл бұрын
@@HinaraT Oh interesting... I assume this behavior is OS-dependent?
@eriks2962
@eriks2962 2 жыл бұрын
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 2 жыл бұрын
"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.
@peircedan
@peircedan 10 ай бұрын
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."
@alias914
@alias914 10 ай бұрын
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.
@thediaclub4781
@thediaclub4781 2 жыл бұрын
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 2 жыл бұрын
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 2 жыл бұрын
​@@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 2 жыл бұрын
@@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 Жыл бұрын
​@@SpeedFlapthe const keyword makes the variable read-only. By default a variable is assumed constant, the volatile keyword removes this constant situation.
@lipcioful
@lipcioful Жыл бұрын
Finally, a great, interesting and professional C content on YT ☺
@StefanNoack
@StefanNoack 2 жыл бұрын
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 2 жыл бұрын
#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 2 жыл бұрын
@@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.
@10vid5
@10vid5 2 жыл бұрын
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.
@tbird-z1r
@tbird-z1r 2 жыл бұрын
Video starts at 3:05
@lukasbelan2109
@lukasbelan2109 2 жыл бұрын
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 2 жыл бұрын
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.
@-wx-78-
@-wx-78- 2 жыл бұрын
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.
@Minty_Meeo
@Minty_Meeo 2 жыл бұрын
And this is why constexpr was added to C++. Edit: It's me. I'm C++ people.
@KelvinShadewing
@KelvinShadewing 2 жыл бұрын
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 2 жыл бұрын
const int i = 5; *(int*)&i = 42;
@_modiX
@_modiX 2 жыл бұрын
const int TEN = 10; // in case ten fluctuates
@HansBezemer
@HansBezemer 2 жыл бұрын
It does when using floating point. ;-)
@andrewporter1868
@andrewporter1868 2 жыл бұрын
@@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.
@davidgillies620
@davidgillies620 10 ай бұрын
I find myself coding C-like code in C++ just so I can take advantage of things like constexpr and compile-time array sizing.
@simonrazer8303
@simonrazer8303 2 жыл бұрын
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.
@flippert0
@flippert0 Жыл бұрын
"C": when it walks like a const, and talks like a const, it's still not a const.
@SassyToll
@SassyToll Жыл бұрын
Thank you, I love your course on C/C++ I have learn so much, I really appreciate what you are doing
@Carolus_64
@Carolus_64 2 жыл бұрын
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
@tonyguillot4998
@tonyguillot4998 2 жыл бұрын
This video makes me remember that Clang is working on improving constexpr and constexpr in C23
@codytubbs
@codytubbs 2 жыл бұрын
even a side-note on differences with Clang and the switch/case A && B example from the video -- compiles just fine. :shrug:
@ABaumstumpf
@ABaumstumpf 2 жыл бұрын
Most of what he said is not actually correct. there is no such thing as "a constant" in C.
@HansBezemer
@HansBezemer 2 жыл бұрын
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 2 жыл бұрын
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 2 жыл бұрын
""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 2 жыл бұрын
@@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 2 жыл бұрын
@@ABaumstumpf And ty you again to clarify this to me in this comment too... :)
@tomaszstanislawski457
@tomaszstanislawski457 Жыл бұрын
`enum { A = 10, B = A + 1 };` will work perfectly fine
@annie3606
@annie3606 2 жыл бұрын
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
@DeveloVooshGWeb
@DeveloVooshGWeb 2 жыл бұрын
it's not a const ant it's a const int
@boristheengineer5160
@boristheengineer5160 11 ай бұрын
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".
@lennymclennington
@lennymclennington 2 жыл бұрын
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.
@ivanscottw
@ivanscottw 2 жыл бұрын
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.
@Invisible12345ful
@Invisible12345ful 2 жыл бұрын
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.
@praktexemplar8082
@praktexemplar8082 2 жыл бұрын
Hey Jacob, great video. I for one would actually love to see a video of pointer magic on const variables.
@euchre90
@euchre90 2 жыл бұрын
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 2 жыл бұрын
@@euchre90 I understand. Thanks for the info!
@primosoma
@primosoma 2 жыл бұрын
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 2 жыл бұрын
In C a constant is a variable that’s value cannot be changed
@HinaraT
@HinaraT 2 жыл бұрын
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 2 жыл бұрын
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 2 жыл бұрын
@@HinaraT 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 2 жыл бұрын
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".
@paulc2448
@paulc2448 2 жыл бұрын
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 2 жыл бұрын
even in C++, most compiler support VLA so if you really need stack allocation just use VLA
@paulc2448
@paulc2448 2 жыл бұрын
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).
@InspektorDreyfus
@InspektorDreyfus 2 жыл бұрын
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 2 жыл бұрын
Try *any* natural number within the 32bit or 64bit range - because that's what it boils down to when preprocessed.
@scottfranco1962
@scottfranco1962 2 жыл бұрын
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 2 жыл бұрын
@@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 2 жыл бұрын
@@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 2 жыл бұрын
​@@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.
@SianaGearz
@SianaGearz 2 жыл бұрын
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 2 жыл бұрын
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 2 жыл бұрын
@@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 2 жыл бұрын
@@SianaGearz Interesting. Luckily that kind of silliness is becoming less common since modern processors are designed with compilers in mind.
@hwstar9416
@hwstar9416 10 ай бұрын
C23 will add `constexpr` fixing the issues you mentioned
@MECHANISMUS
@MECHANISMUS 2 жыл бұрын
Didn't get the problem of switch. Why shouldn't it work?
@ABaumstumpf
@ABaumstumpf 2 жыл бұрын
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.
@simontillson482
@simontillson482 4 ай бұрын
Oh dear. Yes, we know… This is why, if you want to define a commonly used literal, for example, you’d always use a #define - it’s pointless to have a const definition for a literal number, mostly. It does save a little space to use const for 64 bit ints, or double precision floats, though - since compiling the address of a const double occupies less bytes than a literal double would (4 bytes vs 8). If you want a bunch of strings, like error messages however, you wouldn’t want to use #define because it would get compiled into the code every time you reference it and waste a whole bunch of space. That’s why you declare it as a const. Same goes for any static data, or lookup tables. Anyone who doesn’t know this difference really has no business writing C code, IMHO.
@redcrafterlppa303
@redcrafterlppa303 2 жыл бұрын
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 2 жыл бұрын
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 2 жыл бұрын
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 2 жыл бұрын
@@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 2 жыл бұрын
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 2 жыл бұрын
@@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..
@yosef5508
@yosef5508 2 жыл бұрын
Excellent video, but the four constant types in C are worth reviewing.
@johnshaw6702
@johnshaw6702 7 ай бұрын
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.
@raptoress6131
@raptoress6131 2 жыл бұрын
"A const int in C is not a constant." Lol got it
@ABaumstumpf
@ABaumstumpf 2 жыл бұрын
Sadly the video is just wrong about most things.
@teslainvestah5003
@teslainvestah5003 2 жыл бұрын
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.
@BigYoshi826
@BigYoshi826 2 жыл бұрын
You didn't tell us what DOES create a constant
@edgeeffect
@edgeeffect 2 жыл бұрын
Using a different programming language?
@monochromeart7311
@monochromeart7311 2 жыл бұрын
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 2 жыл бұрын
@@edgeeffect Funny, but still a bad answer. C is all you need.
@ABaumstumpf
@ABaumstumpf 2 жыл бұрын
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 2 жыл бұрын
@@ABaumstumpf enums are constant. Also, C23 has constexpr to make things compile-time constant.
@90_98
@90_98 Жыл бұрын
That's why C23 which adds constexpr is so great
@maxaafbackname5562
@maxaafbackname5562 Жыл бұрын
That's the same constexpr as from C++11?
@kreuner11
@kreuner11 2 жыл бұрын
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 2 жыл бұрын
a plain `10` is of type int, no need for the cast
@kreuner11
@kreuner11 2 жыл бұрын
@@czarsonxd2093 yeah, but it when you pass it to another type it will tell you at that point
@programmertotherescue
@programmertotherescue 2 жыл бұрын
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 KZbin 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 2 жыл бұрын
Now I'm curious to see what Jacob has to say about this!
@ABaumstumpf
@ABaumstumpf 2 жыл бұрын
"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 2 жыл бұрын
@@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".
@KangJangkrik
@KangJangkrik 2 жыл бұрын
For other embedded system developers: DO NOT use #define with strings, or the memory usage would be bloated
2 жыл бұрын
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 2 жыл бұрын
@ unfortunately, Arduino IDE won't do this modern optimization. I tested myself and this problem was validated
2 жыл бұрын
@@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 2 жыл бұрын
@ which board you're using? I just tried it and seems like the problem was fixed in Arduino Uno but still apparent on STM32
@JohnDoe-m8i
@JohnDoe-m8i 24 күн бұрын
This video just ended up with me more confused than ever.
@jorgeferreira6727
@jorgeferreira6727 2 жыл бұрын
How about "#define A ((int)10)" in order to have some type check?
@monochromeart7311
@monochromeart7311 2 жыл бұрын
10 is implicitly an int already. 10. or 10.0 would implicitly be doubles.
@jorgeferreira6727
@jorgeferreira6727 2 жыл бұрын
@@monochromeart7311 I know that. But, for some compilers at least, adding an explicit type cast can trigger extra semantic validation.
@monochromeart7311
@monochromeart7311 2 жыл бұрын
@@jorgeferreira6727 if that includes gcc and clang, then thanks for the info!
@jorgeferreira6727
@jorgeferreira6727 2 жыл бұрын
@@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 2 жыл бұрын
@@jorgeferreira6727 you have good points, I will also start adding those casts.
@robert36902
@robert36902 2 жыл бұрын
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 2 жыл бұрын
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 2 жыл бұрын
“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 2 жыл бұрын
Thanks for the replies!
@_CazaBobos
@_CazaBobos 2 жыл бұрын
I know they use the same compiler, but isn't "bool" a c++ specific datatype like "string"?
@TranscendentBen
@TranscendentBen 2 жыл бұрын
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.
@z08840
@z08840 2 жыл бұрын
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 2 жыл бұрын
BUS ERROR
@amekudzilab
@amekudzilab 2 жыл бұрын
Insightful 💡
@martiananomaly
@martiananomaly 2 жыл бұрын
intsightful 😁
@JacobSorber
@JacobSorber 2 жыл бұрын
😂
@ABaumstumpf
@ABaumstumpf 2 жыл бұрын
Sadly oh so wrong.
@sameerplaynicals8790
@sameerplaynicals8790 2 жыл бұрын
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?
@vaibhavsingh-fu1vg
@vaibhavsingh-fu1vg 7 ай бұрын
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; }
@corscheid
@corscheid 2 жыл бұрын
48 things on Git @_@ My 0-notification anxiety is on fire
@leo940806
@leo940806 10 ай бұрын
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?
@PvblivsAelivs
@PvblivsAelivs 2 жыл бұрын
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 2 жыл бұрын
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.
@mikefochtman7164
@mikefochtman7164 2 жыл бұрын
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.
@dixztube
@dixztube 2 жыл бұрын
Malloc shirt. Bruh lmao I love it
@sanderbos4243
@sanderbos4243 2 жыл бұрын
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 2 жыл бұрын
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.
@HinaraT
@HinaraT 2 жыл бұрын
@@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 2 жыл бұрын
@@HinaraT "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 2 жыл бұрын
@@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 2 жыл бұрын
​@@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 "
@WouterStudioHD
@WouterStudioHD 2 жыл бұрын
C23 gets constexpr
@TheBrainDunne
@TheBrainDunne 2 жыл бұрын
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 2 жыл бұрын
ok, I see. use enum for constants then
@justian428
@justian428 2 жыл бұрын
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 2 жыл бұрын
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).
@gdotone1
@gdotone1 4 ай бұрын
the thing to do here is to fix this in the compiler
@nandanvasudevan
@nandanvasudevan 2 жыл бұрын
7:51 I do prefer enum (better would be enum classes) inside a switch...
@euchre90
@euchre90 2 жыл бұрын
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
@portblock
@portblock 2 жыл бұрын
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
@justengineering1008
@justengineering1008 2 жыл бұрын
maybe, we should not mix up maths terms and C terms🤔
@robheusd
@robheusd Жыл бұрын
A constant is not a constant, at least not at sea. But perhaps at land it is?
@Littlefighter1911
@Littlefighter1911 2 жыл бұрын
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...
@TranscendentBen
@TranscendentBen 2 жыл бұрын
I recall something from many years ago that the C standard says a variable is in RAM even if you put a const in front of it. The const only tells the compiler the "variable's" value cannot be changed by assigning a value to it, and that will give a compile error. Of course many embedded C compilers break that rule for practical reasons.
@cellularmitosis2
@cellularmitosis2 2 жыл бұрын
So why hasn’t gcc fixed this yet?
@shriram5494
@shriram5494 2 жыл бұрын
So basically by constant you mean only rvalues?
@cyrilanisimov
@cyrilanisimov 2 жыл бұрын
What about "static const int"?
@HansBezemer
@HansBezemer 2 жыл бұрын
If it's in a module, its name isn't exported. That's all.
@cyrilanisimov
@cyrilanisimov 2 жыл бұрын
@@HansBezemer it should initialized on startup and store in static memory space
@HansBezemer
@HansBezemer 2 жыл бұрын
@@cyrilanisimov Not if it's a global.
@HinaraT
@HinaraT 2 жыл бұрын
@@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.
@gloverelaxis
@gloverelaxis 2 жыл бұрын
it is such a disgrace that the only serious open operating system in the world is written in this language
@kermitdafrog8
@kermitdafrog8 2 жыл бұрын
Why is it a disgrace? What's wrong with the language?
@user-he4ef9br7z
@user-he4ef9br7z 2 жыл бұрын
C is the best programming language. And there are plenty open operating systems, some them are not written in C.
@casperes0912
@casperes0912 2 жыл бұрын
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.
@OSrBurns
@OSrBurns 2 жыл бұрын
C is the best language, mother of the most of the other languages
@monochromeart7311
@monochromeart7311 2 жыл бұрын
@@kermitdafrog8 I'm also interested to know.
@scottfranco1962
@scottfranco1962 2 жыл бұрын
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 2 жыл бұрын
And waste of bytes... :p
@scottfranco1962
@scottfranco1962 2 жыл бұрын
@@sophiacristina Why? I would presume the compiler is smart enough not to allocate it.
@sophiacristina
@sophiacristina 2 жыл бұрын
​@@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 2 жыл бұрын
@@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 2 жыл бұрын
@@scottfranco1962 interesting to know... Ty! :)
@didiTchu
@didiTchu 2 жыл бұрын
why dont you use clion?
@neotune64
@neotune64 2 жыл бұрын
So what should I use then if I want to declare a constant in C?
@v01d_r34l1ty
@v01d_r34l1ty 2 жыл бұрын
By definition, a constant is just a value that doesn’t change. Take that as you will.
@ABaumstumpf
@ABaumstumpf 2 жыл бұрын
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.
@thomassynths
@thomassynths 2 жыл бұрын
FWIW: `#define A ((SomeIntTypedef)1)`
@poloribo23
@poloribo23 2 жыл бұрын
Saying that A+1 isn't a constant is not accurate at all. You're never modifying A at all when you do this operation, and it can be explained with assembly. Of course onstant doesn’t means you can’t do calculus with it. Same when you say that A is not a constant because you can take it’s address and cast it as non const. In C const keyword doesn’t means the memory is not wrirable at all, it means the type is read only. And because C allows a low level access to memory of course you can modify it if you want! You could even retrieve a calling function variable if you wanted to! I think you’re pointing real things about c that can be confusing for beginners, but saying that const isn’t constant is not only confusing, it's also completely inaccurate...
@Voltra_
@Voltra_ 2 жыл бұрын
good old enum trick
@michmart9261
@michmart9261 2 жыл бұрын
You had one job!
@bachvaroff
@bachvaroff Жыл бұрын
enum { A = 10 }; /* good enough, int only */
@trevortrevose9124
@trevortrevose9124 2 жыл бұрын
Can you do a video about consexpr
@Rai_Te
@Rai_Te 8 ай бұрын
Who needs constants?
@AV_YOUTUBE_202X
@AV_YOUTUBE_202X 2 жыл бұрын
_Good ole C_
@bluesillybeard
@bluesillybeard 2 жыл бұрын
In Java (and C# and probably other languages too) thing works (unlike in C), not because it's smart but because under the hood the compiler/interpreter just turns it into an if-else chain. I feel like modern C should be smart enough to do that instead of trying to make whatever it would normally make, even if it's slower. EDIT: I think i've realized why it's not implemented, and it's for two reasons: 1: in C, switch statements represent a jump table, which is inherently static 2:'dynamically' converting it into an if-else chain has several downsides: -performance -expected assembly/machine code output -more complicated compiler
@HansBezemer
@HansBezemer 2 жыл бұрын
Some people use C BECAUSE it works like it works - stupid, but consistent, contrary to what some other retarded compiler makers consider "sane and intelligent behavior that improves the life of programmers". I never actually met a sane person I really liked.
@anon_y_mousse
@anon_y_mousse 2 жыл бұрын
In C a switch is generally turned into a table based jump. Which is why you can't switch on types other than integers. However, you can do things like hash strings before hand and use the hashes as cases. You can even use macros or const's to give them a name so you're not just using a long string of junk.
@ABaumstumpf
@ABaumstumpf 2 жыл бұрын
Also it is just that the video is wrong. there is just no such thing as "a constant" in C. Switch-statements require "constant expressions" - that would be integer literals like "15" or "245689/7+5" or even "(2*5 > 7) ? 1 : 0 " or enums (they are also integral constant expressions).
@pow9606
@pow9606 2 жыл бұрын
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 2 жыл бұрын
What compiler are you using?
@cerulity32k
@cerulity32k 2 жыл бұрын
*(int*)A=100;
Understanding the For Loop (examples in C)
18:37
Jacob Sorber
Рет қаралды 18 М.
Clarifying about literals, macros, and const (still not constant?)
13:14
Turn Off the Vacum And Sit Back and Laugh 🤣
00:34
SKITSFUL
Рет қаралды 7 МЛН
ТВОИ РОДИТЕЛИ И ЧЕЛОВЕК ПАУК 😂#shorts
00:59
BATEK_OFFICIAL
Рет қаралды 6 МЛН
When do I use a union in C or C++, instead of a struct?
11:18
Jacob Sorber
Рет қаралды 70 М.
Should I pass by const reference or by value?
10:45
The Cherno
Рет қаралды 110 М.
Scanf Basics: the good, the bad, and why so many pointers?
15:07
Jacob Sorber
Рет қаралды 24 М.
Your Variables are Not Real.
10:38
Jacob Sorber
Рет қаралды 17 М.
Making variables atomic in C
11:12
Jacob Sorber
Рет қаралды 38 М.
The What, How, and Why of Void Pointers in C and C++?
13:12
Jacob Sorber
Рет қаралды 54 М.
31 nooby C++ habits you need to ditch
16:18
mCoding
Рет қаралды 827 М.
The ONLY C keyword with no C++ equivalent
13:17
mCoding
Рет қаралды 274 М.
Pulling Back the Curtain on the Heap
21:38
Jacob Sorber
Рет қаралды 37 М.
Master Pointers in C:  10X Your C Coding!
14:12
Dave's Garage
Рет қаралды 328 М.