A const int is not a constant.

Поділитися
Вставка
  • Опубліковано 28 вер 2024
  • Patreon ➤ / jacobsorber
    Courses ➤ jacobsorber.th...
    Website ➤ www.jacobsorbe...
    ---
    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.jacobsorbe...
    people.cs.clem...
    persist.cs.clem...
    To Support the Channel:
    + like, subscribe, spread the word
    + contribute via Patreon --- [ / jacobsorber ]
    Source code is also available to Patreon supporters. --- [jsorber-youtub...]

КОМЕНТАРІ • 350

  • @johnheaney3349
    @johnheaney3349 2 роки тому +274

    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 роки тому +67

      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 UA-cam 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

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

  • @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 8 місяців тому +1

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

    • @xcoder1122
      @xcoder1122 8 місяців тому

      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 5 місяців тому

      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.

  • @peircedan
    @peircedan 8 місяців тому +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."

  • @llllNEOllllchannel
    @llllNEOllllchannel 2 роки тому +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 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.

  • @Minty_Meeo
    @Minty_Meeo 2 роки тому +2

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

  • @simontillson482
    @simontillson482 2 місяці тому

    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.

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

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

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

  • @johnshaw6702
    @johnshaw6702 5 місяців тому

    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.

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

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

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

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

  • @amekudzilab
    @amekudzilab 2 роки тому +2

    Insightful 💡

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

  • @robheusd
    @robheusd Рік тому

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

  • @DeveloVooshGWeb
    @DeveloVooshGWeb 2 роки тому +1

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

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

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

  • @shriram5494
    @shriram5494 2 роки тому

    So basically by constant you mean only rvalues?

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

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

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

  • @michmart9261
    @michmart9261 2 роки тому

    You had one job!

  • @captainfordo1
    @captainfordo1 Рік тому

    C23 is getting constexpr.

  • @ilikemorestuff
    @ilikemorestuff 2 роки тому

    Nice choice of topic .. #define has all the power, const is a bandaid.

  • @DanCojocaru2000
    @DanCojocaru2000 2 роки тому +4

    Ah, yes, wrongly named keywords.

    • @ABaumstumpf
      @ABaumstumpf 2 роки тому

      No, just a video being wrong.

    • @chri-k
      @chri-k 2 роки тому

      If you take into account that all type qualifiers are just ( breakable ) promises to the compiler, the name makes makes sense.

    • @ABaumstumpf
      @ABaumstumpf 2 роки тому

      @@chri-k "If you take into account that all type qualifiers are just ( breakable ) promises to the compiler"
      No?
      Breaking them in general is undefined behaviour. Attempting to change the value of a const-variable is undefined - aka you are not allowed to attempt that at all and if you do the compiler can also just ignore whatever you are doing (or burn down your house).

    • @chri-k
      @chri-k 2 роки тому

      @@ABaumstumpf yes, it is undefined because you promised the compiler that you won’t do that. That does not make it impossible.

    • @ABaumstumpf
      @ABaumstumpf 2 роки тому

      @@chri-k "yes, it is undefined because you promised the compiler that you won’t do that."
      No, it is undefined cause the language says so.
      "That does not make it impossible."
      No, it does make it impossible cause you can not, by definition, tell what the program will do. You have no control over it and in most cases the compiler will just ignore the code that does try to modify a const.

  • @greg4367
    @greg4367 2 роки тому +207

    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

  • @ABaumstumpf
    @ABaumstumpf 2 роки тому +35

    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.

  • @xarcaz
    @xarcaz 2 роки тому +43

    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

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

  • @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 роки тому +6

      I've literally fixed bugs changing 1

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

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

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

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

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

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

  • @adecy9669
    @adecy9669 2 роки тому +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 Рік тому +1

      Wait, why is that funnier? 🤔

  • @alias914
    @alias914 8 місяців тому

    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.

  • @vaibhavsingh-fu1vg
    @vaibhavsingh-fu1vg 5 місяців тому

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

  • @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 10 місяців тому

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

  • @boristheengineer5160
    @boristheengineer5160 9 місяців тому

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

  • @tbird81
    @tbird81 2 роки тому +3

    Video starts at 3:05

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

  • @leo940806
    @leo940806 8 місяців тому

    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?

  • @davidgillies620
    @davidgillies620 8 місяців тому

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

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

  • @WouterStudioHD
    @WouterStudioHD 2 роки тому +2

    C23 gets constexpr

  • @hwstar9416
    @hwstar9416 8 місяців тому

    C23 will add `constexpr` fixing the issues you mentioned

  • @tomaszstanislawski457
    @tomaszstanislawski457 Рік тому

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

  • @flippert0
    @flippert0 10 місяців тому

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

  • @thomassynths
    @thomassynths 2 роки тому

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

  • @corscheid
    @corscheid 2 роки тому

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

  • @bachvaroff
    @bachvaroff Рік тому

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

  • @gdotone1
    @gdotone1 2 місяці тому

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

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

  • @justengineering1008
    @justengineering1008 2 роки тому +1

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

  • @cellularmitosis2
    @cellularmitosis2 2 роки тому

    So why hasn’t gcc fixed this yet?

  • @Voltra_
    @Voltra_ 2 роки тому

    good old enum trick

  • @dixztube
    @dixztube 2 роки тому

    Malloc shirt.
    Bruh lmao I love it

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

  • @UrSoMeanBoss
    @UrSoMeanBoss 2 роки тому +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)

  • @90_98
    @90_98 11 місяців тому

    That's why C23 which adds constexpr is so great

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

  • @teslainvestah5003
    @teslainvestah5003 2 роки тому

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

  • @BigYoshi826
    @BigYoshi826 2 роки тому +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.

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

  • @Rai_Te
    @Rai_Te 6 місяців тому

    Who needs constants?

  • @cerulity32k
    @cerulity32k 2 роки тому

    *(int*)A=100;

  • @waldolemmer
    @waldolemmer 2 роки тому

    Useless clickbait.

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

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

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

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

  • @yjc149
    @yjc149 2 роки тому

    me me me!

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

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

  • @SassyToll
    @SassyToll Рік тому

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

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

  • @yosef5508
    @yosef5508 2 роки тому

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

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

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

  • @lipcioful
    @lipcioful Рік тому

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

  • @gloverelaxis
    @gloverelaxis 2 роки тому +4

    it is such a disgrace that the only serious open operating system in the world is written in this language

    • @kermitdafrog8
      @kermitdafrog8 2 роки тому +2

      Why is it a disgrace? What's wrong with the language?

    • @user-he4ef9br7z
      @user-he4ef9br7z 2 роки тому +3

      C is the best programming language.
      And there are plenty open operating systems, some them are not written in C.

    • @casperes0912
      @casperes0912 2 роки тому +1

      There's a proposal to do some parts of Linux in Rust. But what did you have in mind? Pretty much all operating systems ever are composed of C + Assembly.

    • @MrBeanbones
      @MrBeanbones 2 роки тому +3

      C is the best language, mother of the most of the other languages

    • @monochromeart7311
      @monochromeart7311 2 роки тому

      @@kermitdafrog8 I'm also interested to know.

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

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

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

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

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

  • @trevortrevose9124
    @trevortrevose9124 2 роки тому

    Can you do a video about consexpr

  • @didiTchu
    @didiTchu 2 роки тому

    why dont you use clion?

  • @pierreabbat6157
    @pierreabbat6157 2 роки тому

    const int anople=330;

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

  • @AV_YOUTUBE_202X
    @AV_YOUTUBE_202X 2 роки тому

    _Good ole C_

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

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

  • @typedef_
    @typedef_ 2 роки тому +3

    const int is a constant integer variable