A const int is not a constant.

Поделиться
HTML-код
  • Опубликовано: 8 авг 2022
  • Patreon ➤ / jacobsorber
    Courses ➤ jacobsorber.thinkific.com
    Website ➤ www.jacobsorber.com
    ---
    A const int is not a constant // seriously. It's one of the oddest things about C, but it's true. In this video, I'll show you a few examples.
    ***
    Welcome! I post videos that help you learn to program and become a more confident software developer. I cover beginner-to-advanced systems topics ranging from network programming, threads, processes, operating systems, embedded systems and others. My goal is to help you get under-the-hood and better understand how computers work and how you can use them to become stronger students and more capable professional developers.
    About me: I'm a computer scientist, electrical engineer, researcher, and teacher. I specialize in embedded systems, mobile computing, sensor networks, and the Internet of Things. I teach systems and networking courses at Clemson University, where I also lead the PERSIST research lab.
    More about me and what I do:
    www.jacobsorber.com
    people.cs.clemson.edu/~jsorber/
    persist.cs.clemson.edu/
    To Support the Channel:
    + like, subscribe, spread the word
    + contribute via Patreon --- [ / jacobsorber ]
    Source code is also available to Patreon supporters. --- [jsorber-youtube-source.heroku...]

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

  • @johnheaney3349
    @johnheaney3349 Год назад +261

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

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

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

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

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

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

      Weird use of object notation but ok

  • @eddiebreeg3885
    @eddiebreeg3885 Год назад +24

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

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

      @@_Omni A constant and constant expression are two different things in C++. The first simply is something that shouldn't change, the second is something that is known at compile time.

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

      @@eddiebreeg3885 yes

  • @ABaumstumpf
    @ABaumstumpf Год назад +30

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

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

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

    • @reinhold1616
      @reinhold1616 Год назад +8

      pre processor defines are not compile time :)

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

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

    • @xarcaz
      @xarcaz Год назад +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 Год назад +27

    It is worth remembering that when coding for many microcontrollers "const" will place the value in the program store (often times Flash). From a practical point view this means the value will be read-only. This just an addition to already excellent video.

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

      Does this give a performance boost?

    • @harrytsang1501
      @harrytsang1501 Год назад +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 5 месяцев назад +1

      @@jftsang on microcontrollers there is a limited RAM, while program and const data is usually stored in a ROM.

    • @xcoder1122
      @xcoder1122 4 месяца назад

      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 Месяц назад

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

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

    • @HansBezemer
      @HansBezemer Год назад +8

      When preprocessed it is a literal. Believe me.

    • @johnheaney3349
      @johnheaney3349 Год назад +1

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

      All the preprocessor does is just replace every instance of the token with whatever you defined it as. It is really as simple as that, a basic copy/paste. #define A 10 is equivalent to just typing 10 everywhere you typed A. It just takes the magic number out of the code itself and puts it earlier, but when your code compiles it just sees it as though you typed 10 everywhere.

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

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

      ​@@Minty_Meeo Oh yeah so a literal character won't ever use the whole 64 bits. That make sense.

    • @0LoneTech
      @0LoneTech Год назад +6

      I've literally fixed bugs changing 1

  • @eriks2962
    @eriks2962 Год назад +14

    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.

  • @nicholaswood3250
    @nicholaswood3250 Год назад +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)

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

      True. It's a "read only integer variable". If you want a true literal, you use #define. K&R was right.

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

      I was about to comment that, but you beat me to it. Yes, you are absolutely right 😁👍

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

      @@HansBezemer It's still only kind of constant as mentioned in the video due to the fact that you can just edit the memory holding the const int, e.g.
      const int x = 10;
      int* y = &x;
      *y = 11;
      x is now 11

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

      @@sb_dunk Don't do that, in most case it will crash !!! Because the constant might be put into a read-only location meaning that you would segmentation fault on that (that's why using const_cast in C++ is really something you should avoid)
      Even more it can create undefined behaviour into your program because you said that x is now 11 at the end.... Well bad news, you don't know, you fall under the categorie of undefined behaviour, which means anything can happen, and compiler optimization might give you wrong, because the compile can assume that this value didn't change so if you tried to display it even after you though you modified it, might still be considered as 10 by the compiler !

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

      @@TheRobbix1206 Oh interesting... I assume this behavior is OS-dependent?

  • @adecy9669
    @adecy9669 Год назад +3

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

      Wait, why is that funnier? 🤔

  • @llllNEOllllchannel
    @llllNEOllllchannel Год назад +12

    What do you mean under "constant is not really constant but read only entity since we intialized it"? How else would you describe or define constant if it is not just read-only entity?

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

      a constant would have to be assigned to immediately when it is declared, whereas a read-only value could also be assigned to in a constructor

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

      @@v0id_d3m0n calling a constructor is basically "assignment after declaration immediatly". Those are the same things. I still don't see any difference.

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

      As i understand it, what you're doing buy initializing "const A = 10" is impeding yourself from assigning a different value to the A variable, essentially granting yourself read only permission to the A variable.
      What you would still be able to do tho, is create a new int pointer, and assign it the address of A: "int *addr = &A".
      Then you could dereference that pointer and change the value it points to: " *addr = 42 ".
      This way, you effectively changed the value of A.

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

      @@v0id_d3m0n You and OP of this video are redefining what constant means in C.
      That's like learning someone else's language and telling them they're using their own words wrong,
      because you have a different concept of what that word means in another language.
      (For example, you're Japanese and use the term "hamburger", see an American eat something he calls "hamburger"
      and try to correct him that "hamburger" is just the patty)

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

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

    Hello. What if someone uses mmap to allocate memory with the flags PROT_READ and PROT_WRITE, modifies the value of the pointer, then uses mprotect to just change the flags to PROT_READ? Wouldn't that pointer behave like a constant?

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

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

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

  • @SassyToll
    @SassyToll 11 месяцев назад

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

  • @praktexemplar8082
    @praktexemplar8082 Год назад +1

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

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

      @@euchre90 I understand.
      Thanks for the info!

  • @-wx-78-
    @-wx-78- Год назад

    This reminds me of Fortran's numeric literals that are actually variables - they can be modified (mostly by accident) when used as subroutine parameters because of “pass by reference” calling convention.

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

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

      Thanks for the replies!

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

    Before making a video on "exotic" constexpr please explain the const used with pointer and how to declare a
    1) pointer to const variable
    2) const pointer to variable
    3) const pointer to const variable
    I'm programming in C 30 years and with exception case 1 I have always to check books or internet to find syntax for cases 2 and 3

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

    I'd love to see how to do that pointer trick. Don't think I'd ever need it, but it sounds fun to learn.

  • @vaibhavsingh-fu1vg
    @vaibhavsingh-fu1vg 2 месяца назад

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

  • @peircedan
    @peircedan 5 месяцев назад +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."

  • @alias914
    @alias914 4 месяца назад

    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.

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

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

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

    Insightful 💡

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

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

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

      @@TheRobbix1206 yes, I mean the const int is technically a constant, but in some cases the compiler doesn’t treat it as such or imposes limits on its use. As I understand it.

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

      In general it is defined as Wikipedia states, that is: "In computer programming, a constant is a value that should not be altered by the program during normal execution, i.e., the value is constant. When associated with an identifier, a constant is said to be "named," although the terms "constant" and "named constant" are often used interchangeably".
      I'd prefer "cannot be altered" over "should not be altered" because that implies you do dirty stuff like "self modifying code". Furthermore, the definition doesn't address values that are the result of "constant folding" (which means they can be resolved at compile time).
      There has been quite some discussion on the ontology of C - and I think the consensus is (please correct me if I misunderstood) that SOME macros can effectively result in a constant, but that true constants (which are determined at compile time and inlined when used) don't actually exist in C.
      E.g.
      #define TEN 10
      #define ONE 1
      #define ELEVEN (ONE+TEN)
      int main (void)
      {
      int MyArray[ELEVEN];
      MyArray[0] = TEN;
      }
      But is preprocessed to:
      int main (void)
      {
      int MyArray[(1 +10)];
      MyArray[0] = 10;
      }
      Which means the compiler has to do *some* kind of constant folding to size "MyArray".

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

    Macro definitions (#define) work well as constants if you are using primitive types such as int, float, etc. and that works well and you should stick to that. Macro definitions can easily be identified by all caps and are easily found on top of files, editors also like to show them in green color. It's a very good way to define constants.
    Unfortunately it is impossible/impractical to define arrays (strings, structs, etc.) with "#define", however for safety of program sometimes you still want to create array objects that cannot be changed (are immutable). This is where "const" comes handy, because it makes sure nowhere in your program you perform a write operation on your array type variables, hence they become constants.

  • @flippert0
    @flippert0 6 месяцев назад

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

  • @_modiX
    @_modiX Год назад +5

    const int TEN = 10; // in case ten fluctuates

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

      It does when using floating point. ;-)

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

      @@HansBezemer Ah, but you forgot the other asterisk which is that this only occurs if using floats where the float encoding cannot represent all fractions because of the base being coprime with the denominator.
      By the way, it is possible to represent all integers in [0, 2**64] using primorial bases, in this particular case, base (pi(2**64))# where n# denotes the product of all primes prime(1)...prime(n), and pi(n) is the prime counting function. You can get the same using factorial, but primorial here is far more economical since n! grows much faster than n#. Using base (pi(2**64))# guarantees that all fractions (0, 2**(-64)] are guaranteed to have at least one common factor, and therefore a finite representation.

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

    I literally had a technical interview half an hour ago and they asked me this very same question, whether const means constant (of course I said yes)... And youtube of course NOW decides to recommend this.

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

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

    why dont you use clion?

  • @raptoress6131
    @raptoress6131 Год назад +8

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

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

      Sadly the video is just wrong about most things.

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

    Can you do a video about consexpr

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

    So basically by constant you mean only rvalues?

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

      Now I'm curious to see what Jacob has to say about this!

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

      "if an attempt is made to refer to an object"
      Referring to the object is allowed, attempting to modify is not.
      "const int A = 10; int *ptrA = &A;" is well-defined.
      only trying to modify it like with "*ptrA = 2" would be UB.

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

      @@ABaumstumpf Can you point out where exactly in my comment I said otherwise? The part of the comment you're quoting is a part of the clause from the standard that I quoted and it's irrelevant, since it talks about objects defined with a volatile-qualified type, not const-qualified type. The only relevant part is in the emphasis, which says "If an attempt is made to **modify** an object [...] undefined".

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

    EDIT: I just saw the latest video does mention enums but didn't really show the differences much.
    Original comment:
    I'm surprised enums weren't mentioned in this video considering those are an actual way of having a numerical constant which isn't just using preprocessor text replacement to fake it, so the compiler can actually tell which context the enumeration's name refers to the constant and which context it's not being used as a constant. e.g. you can have
    enum {
    A = 10
    };
    And still declare a struct or union or typename called A e.g. "struct A;" (whereas if you use a macro then "struct A;" would just be replaced with "struct 10;" which is not valid)...
    Although maybe it's not the best idea to have those things all called A in the first place, but still it can be done, and I feel like it would've been worth mentioning in this topic.
    Also, constexpr was briefly mentioned in the end, but no mention that constexpr is being added to C in the upcoming C23 standard.

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

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

      @@ABaumstumpf And ty you again to clarify this to me in this comment too... :)

  • @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 Год назад

      #include
      int main()
      {
      const int A = 10;
      int* a_ptr = &A;
      printf("%i
      ", A);
      *a_ptr = 42;
      printf("%i
      ", A);
      return 0;
      }
      Why should A be considered a constant - or are we only talking about file scope?

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

      @@lukasschmitt3075 I mean defining constants is especially helpful for larger projects with multiple files. So you would have the value for the const int in one file but on the usage site the value is not known at compile time. That's why headers and #defines are used for things that need to be known at compile time instead.

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

    This video makes me remember that Clang is working on improving constexpr and constexpr in C23

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

      even a side-note on differences with Clang and the switch/case A && B example from the video -- compiles just fine. :shrug:

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

      Most of what he said is not actually correct. there is no such thing as "a constant" in C.

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

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

  • @tbird81
    @tbird81 Год назад +3

    Video starts at 3:05

  • @davidgillies620
    @davidgillies620 4 месяца назад

    I find myself coding C-like code in C++ just so I can take advantage of things like constexpr and compile-time array sizing.

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

      even in C++, most compiler support VLA
      so if you really need stack allocation just use VLA

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

      If it doesn't compile, it doesn't haha... (Visual Studio 2019) i was amazed that the customized g++ provided with the ps3 sdk was able to do that (several years ago indeed).

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

    C23 will add `constexpr` fixing the issues you mentioned

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

    Mentioning C++ people I would more mention the fact that in C++ this is more clear, due to the fact that you can take const params to indicate that you do intent on using that value readonly, then the fact that C++ has tools for compiletime constants

  • @johnshaw6702
    @johnshaw6702 Месяц назад

    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.

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

    I know they use the same compiler, but isn't "bool" a c++ specific datatype like "string"?

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

      Yes and no! bool is a built-in c++ type just as int is. string is a class and is part of the STL.
      I recall that C99 (the big standard version that has most everything useful in C) has a IIRC stdbool.h header you can include that defines, bool and true and false, but they're not fundamental.

  • @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 Год назад

      Try *any* natural number within the 32bit or 64bit range - because that's what it boils down to when preprocessed.

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

      Same reason const int a; const int b = a+1; didn't used to work. a is not really a constant, its a variable with a property. The compiler has to do extra work to figure out that a actually can be treated as a constant, and it used to not do that but now does. So in the future we can expect case a: ... to work. What that boils down to is the compiler has to make a lot of exceptions to get things to work.

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

      @@scottfranco1962 .. and that's exactly why I don't like it. There is such a thing like "consistent design". Or to paraphrase a famous quote ""You compiler boys were so preoccupied with whether you could, you didn't stop to think if you should."

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

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

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

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

  • @neotune64
    @neotune64 Год назад +1

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

    • @v01d_r34l1ty
      @v01d_r34l1ty Год назад +1

      By definition, a constant is just a value that doesn’t change. Take that as you will.

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

      In C there is no such thing as "a constant".
      "const int A = 10;" defines a constant integer with the value 10 and the identifier 'A'.
      This is a value that can not change (contrary to his claims).
      But this can not be used for say switch-statements cause those require a "constant expression" - which is different from a constant value.
      "1" is a constant expression, same as "6+5/3" is.
      Also enums are constant expression. So if you want to be able to switch on a number that you give a name - that is what enums are for - they are "integer constant expression" hence can be used anywhere C requires a constant expression.
      "#define A 10" is NOT "a constant" (again there is no such thing). Why? Cause defines are not C-code but instructions for the pre-processor to go through the entire document and search-and-replace every occurrence of 'A' and replace it by the number 10 - and that integer-literal is then a constant expression.

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

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

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

    Malloc shirt.
    Bruh lmao I love it

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

      ​@@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 Год назад +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 6 месяцев назад

      ​@@SpeedFlapthe const keyword makes the variable read-only.
      By default a variable is assumed constant, the volatile keyword removes this constant situation.

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

    So why hasn’t gcc fixed this yet?

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

    defining
    const int A = 10;
    assigns storage because it has external linkage. If you were to instead
    static const int A = 10;
    And never reference to it by address in your code within the scope of the file and compile with optimization, this will NEVER occupy any storage area.

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

    const variables placement is implementation defined - it can be allocated in read-only section - don't write to it - it will end badly eventually

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

    You can probably force type checking on a macro by doing ((int)10), then it'll tell you about any implicit cast with the right warning flag

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

      a plain `10` is of type int, no need for the cast

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

      @@czarsonxd2093 yeah, but it when you pass it to another type it will tell you at that point

  • @leo940806
    @leo940806 4 месяца назад

    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?

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

    It's also relevant when you're doing embedded dev and you have a microcontroller with maybe 32kib ROM space (abundant) but only 1kib RAM (scarce), so your variables end up eating into your scarce resource. Then unfortunately every compiler has to come up with its own nonstandard way to declare truly constant constants which are actually in ROM and don't get maintained in RAM.

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

      In general, embedded compilers will place const variables into the ROM space. It's very useful to create large const data structures. No nonstandard features are needed. Check your linker script to see why it might not be doing that.

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

      @@toddblackmon On ARM that is supposed to work, since everything is in the address space. On AVR, a pointer to ROM cannot be taken, it cannot exist, different instructions are used to access ROM and RAM, and same numerical values of address will refer to different locations. So avr-gcc has you declare ROM constants with PROGMEM attribute and access them with functions from pgmspace.h.

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

      @@SianaGearz Interesting. Luckily that kind of silliness is becoming less common since modern processors are designed with compilers in mind.

  • @jorgeferreira6727
    @jorgeferreira6727 Год назад +3

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

      @@monochromeart7311 I know that.
      But, for some compilers at least, adding an explicit type cast can trigger extra semantic validation.

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

      @@jorgeferreira6727 if that includes gcc and clang, then thanks for the info!

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

      @@monochromeart7311 Not sure about those.
      In 30 years, I have used lots of different compilers, both for desktop and embedded systems. The ones for embedded systems tendo to have lots of hardware specific extras, and I may be mixing concepts from a specific compiler.
      Its better try it, or as I do, make sure to don't leave too much guess work for the compiler. Its like using extra parenthesis, even when the operators precedence makes them unnecessary, just to make complex expressions absolutely clear to me and anyone who reads my code.

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

      @@jorgeferreira6727 you have good points, I will also start adding those casts.

  • @MECHANISMUS
    @MECHANISMUS Год назад +1

    Didn't get the problem of switch. Why shouldn't it work?

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

      Cause nothing he said is really correct.
      the "case" requires a "constant expression" and a "const int" is constant, but not a constant expression.
      There just is no such thing as "a constant" in C.

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

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

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

    aren't these just scope issues because you are creating the array and switch function in file scope where it is not determined that the const int is initialized yet.

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

      ok, I see. use enum for constants then

  • @nandanvasudevan
    @nandanvasudevan Год назад +7

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

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

  • @90_98
    @90_98 7 месяцев назад

    That's why C23 which adds constexpr is so great

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

    C23 gets constexpr

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

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

      If you define a const variable in the body of the function as a local or auto then there can only be one path through the switch statement, which would negate the purpose of the switch statement. You can certainly switch on a const parameter to a function.

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

      You can use a "const integer" as long as you put it in the switch() statement:
      #include
      const int x;
      int main (void)
      {
      switch (x) {
      case 0: printf ("It is zero
      ");
      break;
      case 1: printf ("It is one
      ");
      break;
      default: printf ("It is something else
      ");
      break;
      }
      }
      No, it doesn't even generate an error. Yes, it executes. And no, it doesn't display "It's something else".

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

      @@HansBezemer I'm talking about a const int being used as a condition not as the input for the switch. Just like shown in the video.

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

      BTW, not all compilers always compile a switch() statement to an "if else if else if" statement. Some compile it (under certain conditions) to a jumptable - which can REALLY speed up your code, since it only has to calculate the offset and then just perform a jump. If there is a "hole" before your range, it can "clip" the value to a minimal value. Same for a "hole" at the end of the range.

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

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

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

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

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

    of course not. in order to make an const int into a constant, you have to solve for its mother's sister. its constaunt.
    She runs a restaurant with a lot of drawbacks - mainly that she employs only escaped serial killers for cooks and pirates for waiters.
    The eggs and the toast escape unscathed. So they don't sell well. When we go there, we never get that bread. And when the police come by for coffee, the waiters all make like the eggs and rum.

  • @cyrilanisimov
    @cyrilanisimov Год назад +1

    What about "static const int"?

    • @HansBezemer
      @HansBezemer Год назад +1

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

    • @cyrilanisimov
      @cyrilanisimov Год назад +1

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

    • @HansBezemer
      @HansBezemer Год назад +1

      @@cyrilanisimov Not if it's a global.

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

      @@cyrilanisimov It should be initialized BEFORE startup, that's why most compiler put static const under a readonly section of your program.
      So it is not really initialized like setting it's value by hand, but rather by just putting the corresponding space of your program to the address required by the program.

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

      And waste of bytes... :p

    • @scottfranco1962
      @scottfranco1962 Год назад +1

      @@sophiacristina Why? I would presume the compiler is smart enough not to allocate it.

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

      ​@@scottfranco1962 tbh, i don't know how far compilers works with that, but, by what i learned, not. I'm not a pro, someone correct me if i'm wrong.
      But... It happens because when you declare a const, that is like saying to the compiler "i WANT a space in the memory". The compiler would think "if you have not used macro, so you want a space in the memory" (it wasn't pre-processed), this happens because a const int (or type) can be accessed with pointers and reference, while a macro can't. This can't work without memory space, if the compiler is smart enough to notice if you never used pointers / reference, i'm too lay to know, and then, sorry for that. A const is just like any type, but the value can't be changed, but it acts like an variable. That is why "a const is not a const", because it is basically a non-modifiable variable. Sounds confusing, don't?
      Summarizing, you are telling the compiler that you need something that can also be accessed by the memory location...

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

      @@scottfranco1962 interesting to know... Ty! :)

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

    I'm very confused. Maybe you should have started by stating what "constant" means, and why a const int is not a constant... Can anyone explain to me?

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

      Because its in fact is a read-only variable. To understand the difference you should code in any language that have both concepts. Like C# where you can use both 'const int x' (will be a true constant, by behavior its closer to #define macro in C) and 'static readonly int x' (effectively works similar to C const).

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

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

    good old enum trick

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

    You had one job!

  • @justengineering1008
    @justengineering1008 Год назад +1

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

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

    You didn't tell us what DOES create a constant

    • @edgeeffect
      @edgeeffect Год назад +3

      Using a different programming language?

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

      @@edgeeffect Funny, but still a bad answer. C is all you need.

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

      Simple: NOTHING:
      C does not have a thing that is "a constant"... sadly most of his assertions in this video are wrong.
      "const int A = 10;" does define a constant integer. Simpel as that.
      But things like initialising a const-int requires a constant EXPRESSION and that is just something different. Any literal is a constant expression - so "34634" is, or "10+5*2" is also a constant expression.
      If you want to have a name for a specific value - that is what enums are for.
      Also with 'define' you do not get constants cause defines are just simple string-replacements. The compiler NEVER sees them. When you use "#define A 10" all that this does is that before the compiler gets the source it scans the files and replaces every single occurrence of 'A' with whatever string you gave it - in that case '1' - so an integer literal.
      (also no, contrary to his claims it is not possible to change the value of 'A' as that was declared as being const)

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

      @@ABaumstumpf enums are constant.
      Also, C23 has constexpr to make things compile-time constant.

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

    For other embedded system developers: DO NOT use #define with strings, or the memory usage would be bloated

    •  Год назад

      And this behavior is compiler dependent. Modern compilers can perform optimization for case like that and allocate storage once. Some linkers can do same job for duplicated symbols across different modules. For same reason const can be a real constant, there are plenty different platforms with different architectures, compilers, operating systems and hardware extensions, even present x86 can use memory protection to avoid changing application code at runtime.

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

      @ unfortunately, Arduino IDE won't do this modern optimization. I tested myself and this problem was validated

    •  Год назад

      @@KangJangkrik, can you give any example? In single file I can't reproduce this behavior, I can use many times same literal with macro as function argument, assigning it to different const, etc. And program size doesn't change at all when I use string literal once and when I use it many times.
      Arduino use GCC and GCC performs well for optimizations like this, it has even option to do same optimization at link time (merge-constants).

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

      @ which board you're using? I just tried it and seems like the problem was fixed in Arduino Uno but still apparent on STM32

  • @georgecop9538
    @georgecop9538 Год назад +1

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

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

      Legend

    • @user-he4ef9br7z
      @user-he4ef9br7z Год назад

      You'd have to always be in a TempleOS Virtual Machine. There's no way to run it on other OSs, otherwise I'd have switched too.
      On top of that it's JIT compiled. So I think it's slower.

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

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

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

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

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

    It's a very simple rule: If it exists in memory, it is not a constant. There is a similar problem with "null" pointers. Address 0 exists.

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

      This is true in practice, but is also dangerous to use. Even if your machine has address 0 it is invalid to represent it as null pointer. And with constants - i believe if your code can observe change of a constant, it can do so only via undefined behavior.

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

      Define "memory".
      ROM is (also) memory.

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

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

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

    _Good ole C_

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

    *(int*)A=100;

  • @UrSoMeanBoss
    @UrSoMeanBoss Год назад +1

    As a pedantic asshole, I find this video quite troubling.... But I guess from a layman's point of view, it's informative. Fine.
    BUT!! regarding the modification of a const-qualified variable via pointer arithmetic, you should be VERY careful to explain that it's undefined behavior in the eyes on the language. That may require a slightly deeper discussion about the language specification and how it views specified/unspecified/impl. defined/undefined, and how all those boil down to conceptual "guarantees" (whether the language, the platform, the implementation, or dumb luck is guaranteeing the behavioral correctness of your program)

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

    The Array creation and the switch statement compile just fine. Even with Warning level set to maximum of 4.
    I was slightly unsure about the array creation but after thinking about it, I expect it to compile fine.
    The A and B variables are created by the time the compiler gets to the array creation statement.
    The switch statement should never be a problem because the const variable is just being compared.
    A const variable cannot be assigned to unless by pointer or recasting away the const.
    I suggest you check your compiler and change to a compiler version that works properly.

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

    Who needs constants?

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

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

      @@sanderbos4243 I don't see any defined behaviour on the stack overflow post, just that it is used for strstr, but as strstr is implementation defined this is not a problem

    • @sanderbos4243
      @sanderbos4243 Год назад +1

      @@TheRobbix1206 "But if the caller passes you a pointer to data that in fact is mutable, then behavior is defined. Creating a const char* that points to a modifiable char doesn't make that char immutable." from the accepted answer on that post.
      I really like the first comment under that as well: "(im)mutability is an inherent property of the object itself, regardless of the qualification of the pointer used to access it"

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

      @@sanderbos4243 yeah, iirc, you can 'safely' remove const away if the object is not living in 'read-only' memory; bascially all global/static consts, string literals.

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

      ​@@rmaster934 No. You can ALWAYS safely "remove" the const, but you can ONLY safely manipulate the object if the object it self is not const.
      Aka
      "const int A = 10;
      int *ptrA = &A; -- non-const pointer is well defined and allowed
      printf("ptrA=%p *ptrA=%d", (void*)ptrA, *ptrA);
      // *ptrA = 2; changing the object would be undefined behaviour
      "

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

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

    4:33 you could not. Try it, in a future video.
    It's a constant.
    The compiler treats the const as constant and will replace the value as if it was a literal, but otherwise check the syntax as if it was of that type (even if it allocates a sizeof(int) big variable in .rodata and therefor has a pointer to it). That's the point of using const.
    It doesn't matter, if you replaced the value that it points to, as long as it's not been passed as a pointer into a function,
    that has not been inlined by the compiler.
    Stop spreading misinformation by the lack of testing and assuming.
    Just compile your example with -S and look at the output.
    If you don't use your "&A" but "A" and use "%d" for formatting, you will see it pushing the value "10" on stack (or to the appropriate registers), regardless of if you change it afterwards.
    To be more precise, you can't even cast away the const, as the section it will land in will be read-only on most systems and therefor crash if you try rewriting it.
    Thus it's a constant, yeah it might not be able to be picked up by the pre-processor at all times, but it's still a constant.
    8:23 That's not valid. You can't use ints in a case. That's not how C works. It's still a constant.
    It's not a integer literal. But if you were to call it that, the title wouldn't have been clickbaity enough....
    What you did, is redefining what a constant is in C and then say it's not constant, for your 9 minute video of internet spew.
    Just as Pannenkoeck with his BS excuse of introducing the term half-button-press and parallel universe.
    Some people seem to celebrate this internet spew...

  • @captainfordo1
    @captainfordo1 11 месяцев назад

    C23 is getting constexpr.

  • @DeveloVooshGWeb
    @DeveloVooshGWeb Год назад +1

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

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

    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.

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

    In C# you have readonly and const..

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

      Yet more reason to hate C#. It would've been super easy to just change the behavior of const, it was a new language once, or even to excise the keyword to avoid confusion with C and C++, but instead they leave it and add extra keywords and at that two word keywords. It makes me sad that it just won't die as a language.

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

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

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

      @SlowSunsetVibes It does affect me, though. I'm far too often forced to use it. It's a garbage language that only exists because Sun wouldn't bend over and do whatever Microsoft wanted. Only makes it worse that Java was a garbage language already and C# degraded the quality from there.

  • @typedef_
    @typedef_ Год назад +3

    const int is a constant integer variable

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

    const int anople=330;