A const int is not a constant.

Поделиться
HTML-код
  • Опубликовано: 2 дек 2024

Комментарии •

  • @johnheaney3349
    @johnheaney3349 2 года назад +277

    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 года назад +69

      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 года назад +5

      Thanks for cleaning up the ontology of C used here. I recently did a RUclips 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 года назад +3

      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 года назад +5

      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 года назад +1

      @@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 года назад +208

    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 года назад +25

      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 года назад +17

      Me: **removes exception from PhysicsEngine*
      Problem solved :)

    • @tk36_real
      @tk36_real 2 года назад +3

      "differences in use of volatile, const" - there are none, they are syntactically equivalent

    • @paulc2448
      @paulc2448 2 года назад +2

      label 'language' was undefined.

    • @dangnabbit1379
      @dangnabbit1379 2 года назад +1

      Weird use of object notation but ok

  • @eddiebreeg3885
    @eddiebreeg3885 2 года назад +28

    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 года назад +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 года назад +4

      @@_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 года назад +37

    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 года назад +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 года назад +3

      @@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 года назад +4

      "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.

  • @georgecop9538
    @georgecop9538 2 года назад +39

    2:17 You can #undef and then redefine with a new value. It's not really a constant, just a macro

    • @HansBezemer
      @HansBezemer 2 года назад +9

      When preprocessed it is a literal. Believe me.

    • @johnheaney3349
      @johnheaney3349 2 года назад +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 года назад +3

      @@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 года назад +4

      @@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.

  • @xarcaz
    @xarcaz 2 года назад +44

    It IS a constant. Just not a compile-time constant (such as pre-processor defines, enum values, and C++ constexpr values).

    • @reinhold1616
      @reinhold1616 2 года назад +8

      pre processor defines are not compile time :)

    • @xarcaz
      @xarcaz 2 года назад +1

      @@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 года назад +3

      @@xarcaz i meant that defines are evaluated by the pre processor which runs before the compiler

    • @xarcaz
      @xarcaz 2 года назад +1

      @@reinhold1616 Oh, I definitely agree with that. I just meant the common constant expression usage cases, not all macro cases. :)

    • @tomaszstanislawski457
      @tomaszstanislawski457 Год назад +4

      btw... `constexpr` will be added to upcoming C23 standard

  • @knightflyer909
    @knightflyer909 2 года назад +28

    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 года назад +3

      @@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 11 месяцев назад +1

      @@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.

  • @Siger5019
    @Siger5019 2 года назад +37

    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 года назад +3

      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 года назад +1

      @@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 года назад +5

      I've literally fixed bugs changing 1

  • @parthbansal2775
    @parthbansal2775 2 года назад +4

    Not to state the obvious but a const int will be a constint and not a constant. I will see myself out

  • @eriks2962
    @eriks2962 2 года назад +15

    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 года назад +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.

  • @llllNEOllllchannel
    @llllNEOllllchannel 2 года назад +13

    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 года назад +1

      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.

  • @peircedan
    @peircedan 11 месяцев назад +1

    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."

  • @maxaafbackname5562
    @maxaafbackname5562 2 года назад +19

    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 года назад +3

      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?

  • @adecy9669
    @adecy9669 2 года назад +4

    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 Год назад +1

      Wait, why is that funnier? 🤔

  • @nicholaswood3250
    @nicholaswood3250 2 года назад +5

    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)

  • @StefanNoack
    @StefanNoack 2 года назад +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.

  • @thediaclub4781
    @thediaclub4781 2 года назад +1

    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 года назад +1

      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 года назад +1

      @@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.

  • @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.

  • @primosoma
    @primosoma 2 года назад +3

    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 года назад +4

      In C a constant is a variable that’s value cannot be changed

    • @HinaraT
      @HinaraT 2 года назад +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 года назад +1

      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".

  • @DeveloVooshGWeb
    @DeveloVooshGWeb 2 года назад +1

    it's not a const ant
    it's a const int

  • @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

  • @Minty_Meeo
    @Minty_Meeo 2 года назад +2

    And this is why constexpr was added to C++.
    Edit: It's me. I'm C++ people.

  • @nandanvasudevan
    @nandanvasudevan 2 года назад +7

    7:51 I do prefer enum (better would be enum classes) inside a switch...

    • @euchre90
      @euchre90 2 года назад +1

      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

  • @10vid5
    @10vid5 2 года назад +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.

  • @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?

  • @lipcioful
    @lipcioful Год назад

    Finally, a great, interesting and professional C content on YT ☺

  • @programmertotherescue
    @programmertotherescue 2 года назад +4

    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 RUclips 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".

  • @simonrazer8303
    @simonrazer8303 2 года назад +1

    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.

  • @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;
    }

  • @InspektorDreyfus
    @InspektorDreyfus 2 года назад +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 года назад +1

      @@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.

  • @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.

  • @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.

  • @tbird-z1r
    @tbird-z1r 2 года назад +3

    Video starts at 3:05

  • @HansBezemer
    @HansBezemer 2 года назад +1

    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 года назад +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 года назад +1

      @@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... :)

  • @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 года назад +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.

  • @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.

  • @redcrafterlppa303
    @redcrafterlppa303 2 года назад +3

    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 года назад +1

      @@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..

  • @jorgeferreira6727
    @jorgeferreira6727 2 года назад +3

    How about "#define A ((int)10)" in order to have some type check?

    • @monochromeart7311
      @monochromeart7311 2 года назад +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.

  • @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.

  • @flippert0
    @flippert0 Год назад

    "C": when it walks like a const, and talks like a const, it's still not a const.

  • @robert36902
    @robert36902 2 года назад +1

    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 года назад +1

      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 года назад +4

      “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!

  • @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.

  • @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.

  • @_modiX
    @_modiX 2 года назад +5

    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.

  • @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".

  • @-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.

  • @SassyToll
    @SassyToll Год назад

    Thank you, I love your course on C/C++ I have learn so much, I really appreciate what you are doing

  • @hwstar9416
    @hwstar9416 10 месяцев назад

    C23 will add `constexpr` fixing the issues you mentioned

  • @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

  • @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...

  • @praktexemplar8082
    @praktexemplar8082 2 года назад +1

    Hey Jacob, great video.
    I for one would actually love to see a video of pointer magic on const variables.

    • @euchre90
      @euchre90 2 года назад +1

      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 года назад +1

      @@euchre90 I understand.
      Thanks for the info!

  • @tomaszstanislawski457
    @tomaszstanislawski457 Год назад

    `enum { A = 10, B = A + 1 };` will work perfectly fine

  • @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.

  • @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.

  • @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

  • @neotune64
    @neotune64 2 года назад +1

    So what should I use then if I want to declare a constant in C?

    • @v01d_r34l1ty
      @v01d_r34l1ty 2 года назад +1

      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.

  • @MECHANISMUS
    @MECHANISMUS 2 года назад +1

    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.

  • @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?

  • @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.

  • @sanderbos4243
    @sanderbos4243 2 года назад +3

    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 года назад +1

      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 года назад +1

      @@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
      "

  • @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.

  • @_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

  • @paulc2448
    @paulc2448 2 года назад +1

    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).

  • @portblock
    @portblock 2 года назад +1

    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

  • @BigYoshi826
    @BigYoshi826 2 года назад +4

    You didn't tell us what DOES create a constant

    • @edgeeffect
      @edgeeffect 2 года назад +3

      Using a different programming language?

    • @monochromeart7311
      @monochromeart7311 2 года назад +1

      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.

  • @raptoress6131
    @raptoress6131 2 года назад +8

    "A const int in C is not a constant." Lol got it

    • @ABaumstumpf
      @ABaumstumpf 2 года назад +2

      Sadly the video is just wrong about most things.

  • @yosef5508
    @yosef5508 2 года назад

    Excellent video, but the four constant types in C are worth reviewing.

  • @amekudzilab
    @amekudzilab 2 года назад +2

    Insightful 💡

  • @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

  • @cyrilanisimov
    @cyrilanisimov 2 года назад +1

    What about "static const int"?

    • @HansBezemer
      @HansBezemer 2 года назад +1

      If it's in a module, its name isn't exported. That's all.

    • @cyrilanisimov
      @cyrilanisimov 2 года назад +1

      @@HansBezemer it should initialized on startup and store in static memory space

    • @HansBezemer
      @HansBezemer 2 года назад +1

      @@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.

  • @didiTchu
    @didiTchu 2 года назад

    why dont you use clion?

  • @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).

  • @mikefochtman7164
    @mikefochtman7164 2 года назад +1

    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.

  • @shriram5494
    @shriram5494 2 года назад

    So basically by constant you mean only rvalues?

  • @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

  • @90_98
    @90_98 Год назад

    That's why C23 which adds constexpr is so great

  • @scottfranco1962
    @scottfranco1962 2 года назад +1

    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 года назад +1

      @@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 года назад +1

      @@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! :)

  • @thomasweller7235
    @thomasweller7235 Год назад

    @6:47 The variable length array support is a compiler extension. It's not Standard C++. Compile with -Werror=vla

  • @justengineering1008
    @justengineering1008 2 года назад +1

    maybe, we should not mix up maths terms and C terms🤔

  • @WouterStudioHD
    @WouterStudioHD 2 года назад +2

    C23 gets constexpr

  • @JohnDoe-m8i
    @JohnDoe-m8i Месяц назад

    This video just ended up with me more confused than ever.

  • @cellularmitosis2
    @cellularmitosis2 2 года назад

    So why hasn’t gcc fixed this yet?

  • @trevortrevose9124
    @trevortrevose9124 2 года назад

    Can you do a video about consexpr

  • @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.

  • @robheusd
    @robheusd Год назад

    A constant is not a constant, at least not at sea. But perhaps at land it is?

  • @gdotone1
    @gdotone1 5 месяцев назад

    the thing to do here is to fix this in the compiler

  • @corscheid
    @corscheid 2 года назад

    48 things on Git @_@
    My 0-notification anxiety is on fire

  • @georgecop9538
    @georgecop9538 2 года назад +1

    I can say I switched from C to HolyC (and TempleOS). Would you do an episode on that?

    • @Hellohiq10
      @Hellohiq10 2 года назад

      Legend

    • @user-he4ef9br7z
      @user-he4ef9br7z 2 года назад

      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 2 года назад

      @@user-he4ef9br7z It compiles things before it runs them, but it does it really fast, even through a VM.

  • @dixztube
    @dixztube 2 года назад

    Malloc shirt.
    Bruh lmao I love it

  • @bachvaroff
    @bachvaroff Год назад

    enum { A = 10 }; /* good enough, int only */

  • @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.

  • @thomassynths
    @thomassynths 2 года назад

    FWIW: `#define A ((SomeIntTypedef)1)`

  • @typedef_
    @typedef_ 2 года назад +3

    const int is a constant integer variable

  • @justwatching6118
    @justwatching6118 2 года назад

    In C# you have readonly and const..

    • @anon_y_mousse
      @anon_y_mousse 2 года назад

      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_ 2 года назад

      @@anon_y_mousse C# is a superb programming language in every aspect.

    • @anon_y_mousse
      @anon_y_mousse 2 года назад

      @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.

  • @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...

  • @Rai_Te
    @Rai_Te 8 месяцев назад

    Who needs constants?

  • @Voltra_
    @Voltra_ 2 года назад

    good old enum trick

  • @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.

  • @cerulity32k
    @cerulity32k 2 года назад

    *(int*)A=100;