Stories
Slash Boxes
Comments

SoylentNews is people

SoylentNews is powered by your submissions, so send in your scoop. Only 19 submissions in the queue.
posted by Fnord666 on Sunday August 25 2019, @01:57PM   Printer-friendly
from the quite-the-contrary dept.

Submitted via IRC for SoyCow3196

Why const Doesn't Make C Code Faster

In a post a few months back I said it's a popular myth that const is helpful for enabling compiler optimisations in C and C++. I figured I should explain that one, especially because I used to believe it was obviously true, myself. I'll start off with some theory and artificial examples, then I'll do some experiments and benchmarks on a real codebase: Sqlite.

Let's start with what I used to think was the simplest and most obvious example of how const can make C code faster. First, let's say we have these two function declarations:

void func(int *x);
void constFunc(const int *x);

And suppose we have these two versions of some code:

void byArg(int *x)
{
  printf("%d\n", *x);
  func(x);
  printf("%d\n", *x);
}

void constByArg(const int *x)
{
  printf("%d\n", *x);
  constFunc(x);
  printf("%d\n", *x);
}

To do the printf(), the CPU has to fetch the value of *x from RAM through the pointer. Obviously, constByArg() can be made slightly faster because the compiler knows that *x is constant, so there's no need to load its value a second time after constFunc() does its thing. It's just printing the same thing. Right? Let's see the assembly code generated by GCC with optimisations cranked up:


Original Submission

 
This discussion has been archived. No new comments can be posted.
Display Options Threshold/Breakthrough Mark All as Read Mark All as Unread
The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
(1)
  • (Score: -1, Troll) by Anonymous Coward on Sunday August 25 2019, @02:20PM (8 children)

    by Anonymous Coward on Sunday August 25 2019, @02:20PM (#885173)

    They could try using ProggyClean with blackboard theme for readability. Code-wise, they could use Contributor Covenant to squash any inclusivity bugs.

    • (Score: 0) by Anonymous Coward on Sunday August 25 2019, @02:46PM (4 children)

      by Anonymous Coward on Sunday August 25 2019, @02:46PM (#885185)

      inclusivity bugs

      Here we go, was not enough to watch for null pointers and bounds but now also for minorities and LGTB code.
      What's next, an FSM exception code?

      • (Score: 3, Funny) by The Mighty Buzzard on Sunday August 25 2019, @02:56PM

        Nope, exceptions are problematic since they imply that the caller is somehow exceptional.

        --
        My rights don't end where your fear begins.
      • (Score: 0) by Anonymous Coward on Sunday August 25 2019, @07:28PM (1 child)

        by Anonymous Coward on Sunday August 25 2019, @07:28PM (#885331)

        What should I do if my NullPointerException has completed hir transition from an ArrayOutOfBoundsException?

      • (Score: 0) by Anonymous Coward on Monday August 26 2019, @03:03PM

        by Anonymous Coward on Monday August 26 2019, @03:03PM (#885662)

        More like the owners and managers who recognize harassment and gay bashing don't hire people who create hostile work environments, and intelligent open source projects don't give a shit about your mad skillz until you learn to be a human being who doesn't hold people's sexual orientations or physiologic characteristics against them.

        I suppose you're against working with all them cripples and darkies too.

    • (Score: 0) by Anonymous Coward on Sunday August 25 2019, @02:57PM (2 children)

      by Anonymous Coward on Sunday August 25 2019, @02:57PM (#885195)

      Please don't let this guy on our team. Please don't let this guy on our team. Please don't let...

      • (Score: 0) by Anonymous Coward on Sunday August 25 2019, @06:48PM (1 child)

        by Anonymous Coward on Sunday August 25 2019, @06:48PM (#885298)

        You are just scared the boss will find out your code is riddled with exclusivity.

        • (Score: 0) by Anonymous Coward on Monday August 26 2019, @10:50AM

          by Anonymous Coward on Monday August 26 2019, @10:50AM (#885589)

          Yes, it's scary. She may get promoted and asked to supervise snowflake's blackbox gay code, and that sucks.

  • (Score: 5, Insightful) by Dr Spin on Sunday August 25 2019, @03:02PM (3 children)

    by Dr Spin (5239) on Sunday August 25 2019, @03:02PM (#885197)

    ... by using const - with two printf()s in there?

    WTF?

    You could save two whole CPU cycles out of about 5k cycles?

    Besides which, if the value does not change, then the optimiser should create the same code whether const is there or not.
    What machine architecture are you using, with what caching? Have you looked at the code this generates? Could you
    read it anyway?

    Compiler writers are mostly very clever* people, and most C compilers have had more than 10 years of optimisation.

    * probably also autistic, OCD and fanatic about saving 1/2 a CPU cycle in even the most obscure cases, and definitely
    out to prove they are better than the last guy.

    --
    Warning: Opening your mouth may invalidate your brain!
    • (Score: 0, Touché) by Anonymous Coward on Sunday August 25 2019, @09:08PM (2 children)

      by Anonymous Coward on Sunday August 25 2019, @09:08PM (#885377)

      saving 2 cycles out of 5k cycles, for a single pass, your right why waste the time.

      Now call it 2G times... That is real processing power waste.

      • (Score: 0) by Anonymous Coward on Monday August 26 2019, @06:34AM (1 child)

        by Anonymous Coward on Monday August 26 2019, @06:34AM (#885540)

        By your logic putting two lines of code in a function and calling the function 2k times is the real rea processing power waste. Calling functions is expenssive.

        • (Score: 2) by Pino P on Monday August 26 2019, @03:36PM

          by Pino P (4721) on Monday August 26 2019, @03:36PM (#885677) Journal

          Finding opportunities to expand a function inline as if it were a macro is why compiler developers invented link-time optimization (LTO). SQLite uses a related technique called "amalgamation," where the entire library is compiled as a single translation unit.

  • (Score: 2, Interesting) by isj on Sunday August 25 2019, @03:10PM (9 children)

    by isj (5249) on Sunday August 25 2019, @03:10PM (#885200) Homepage

    I assume that many C/C++ programmers already knew that const doesn't necessarily improve performance. But it's still good that there is an article about it so younglings can learn - we old farts are not always that good at disseminating knowledge like that.

    I don't like that the article's first proof is the generated assembly, but I guess that quoting chapter and verse(s) from the C standard would have made most readers eyes glaze over. I think it would have been better to first show in source code why the compiler cannot assume that the pointed-to contents of a const pointer cannot change, then quote chapter and verse from the standard, then finally prove it with generated assembly.

    • (Score: 5, Informative) by Ethanol-fueled on Sunday August 25 2019, @03:32PM (4 children)

      by Ethanol-fueled (2792) on Sunday August 25 2019, @03:32PM (#885206) Homepage

      The point of const is to make variables immutable so people don't fuck with them, not optimize for speed.

      • (Score: 2, Informative) by Anonymous Coward on Sunday August 25 2019, @04:44PM (1 child)

        by Anonymous Coward on Sunday August 25 2019, @04:44PM (#885229)

        I was waiting for someone to point this out.

        Furthermore at least back in the DOS, proprietary unix and 8bit days, I seem to remember it providing other benefits that could speed things up, but it was a secondary effect mostly due to the optimization paths compilers of the day used.

        const's primary purpose has always been to ensure a pointer is immutable within the context of the C code itself. Writing in assembly could always bypass it and certain C compilers would fail to take it into account in all circumstances if you were particularly 'creative' with your means of access or rewriting of the pointer. But if you were following the standards for data typing, const was there to protect your functions or data structure from someone doing something stupid or malicious while working with a pointer or data structure.

        We used to call them clobbering vs non-clobbering functions which either modified in place, or had to create and return a new copy of a data structure with a new pointer in order to ensure consistency in the codebase. It was the tradeoff between memory consumption and ensuring a sane program state in the older memory constrained days of application and operating system development.

        • (Score: 2, Informative) by Anonymous Coward on Sunday August 25 2019, @06:49PM

          by Anonymous Coward on Sunday August 25 2019, @06:49PM (#885299)

          Look at his command line.

          gcc -S -Wall -O3 test.c

          That is the most aggressive optimization switch. Two of those are basic constant folding and basic constant propagation. When compiling, it can look and determine both of the variables, despite only one being marked, are not changed during actual execution and makes such a substitution, when it believes it is safe to do so. To your point, when GCC compilers were dumber "const" was important because it would signal the compiler you could handle the constants that way and it didn't have to guess whether or not it was safe.

          And that doesn't get into any other black magic the -O3 switch will do. If anything, he should have shown what a bare command line, -O, -O2, and -Os, all against the same code. He is smart enough to know the difference between a t test and a U test (although not that these are dependent samples and a different test should be used). I reckon he is smart enough to try and show the difference that way.

      • (Score: 0) by Anonymous Coward on Monday August 26 2019, @12:10AM

        by Anonymous Coward on Monday August 26 2019, @12:10AM (#885437)

        const doesn't necessarily make objects immutable though. The variable can be changed elsewhere. const instead specifies access permissions to a variable.

      • (Score: 0) by Anonymous Coward on Monday August 26 2019, @04:24PM

        by Anonymous Coward on Monday August 26 2019, @04:24PM (#885693)

        Yeah but that's why God had to invent const_cast to override the excessive use of const by others to protect us.

    • (Score: 2, Interesting) by Anonymous Coward on Sunday August 25 2019, @09:20PM (3 children)

      by Anonymous Coward on Sunday August 25 2019, @09:20PM (#885383)

      I once spent several weeks arguing with one of my fellow senior engineer's over this exact thing.

      I *SHOWED* him how it was not doing anything. He had spent 2 weeks putting 'const' all over the code. Before functions in the api, in params, ... everywhere.

      He was one of those show off programmers that 'knew better' than everyone else. Would just nod smugly when I showed him how very very very wrong he was. Then ignore the advice of anyone on the team then yell at them because they did not follow his style guide which was only in his head. Ignoring the one the team had already agreed to and was doc'd in the wiki.

      Fucker you wasted a whole sprint fucking around with this?! The API did not need to be changed because it did not match the style guide from your former company. In fact it did not match the current company you worked at style guide.

      If you can not tell me what it is doing to your code get the fuck rid of it. I am reverting your whole sprints work because it adds no new features and only makes using variables harder for little gain. You wasted 5 hours of my time because I thought you were competent. Not anymore as now I have to extra scrutinize what you are doing and have to instruct others to do the same.

      Considering how many F bombs I am dropping you may think I was upset about this. Yes. Yes I am. I am usually fairly easy going with most changes. Because they are usually just fine. But this one was just too much.

      Constexpr in C++ on the other had has *tons* of uses. But put a const in their alongside it? Well you can just kiss your pre-compiled optimizations goodbye as const is a value decided at runtime thing. More along this thing is set here in code once and never modified again. While constexpr you can figure it out at compile time.

      Const is for things like where you would do something like #define XYZ 2. That has its uses and a nice way to enforce type. But even then not always needed.
      Not for every parameter and every function you can lay your hands on.

      Now do not get me wrong const has its uses. It is a modifier that should be used when needed, not dictated by style.

      What riles me up is the style nazis have glommed ont this this as something that is 'better' with no real reasons as to what the expression actually does. This is not so much a big deal anymore but it even varies between compiler sets what it actually does. The spec says what it does not what the compiler should with the optimizer in this case other than a delineation point of what can be optimized. That portion is usually an assumption by the programmer. Usually it is wrong.

      • (Score: 5, Informative) by Immerman on Monday August 26 2019, @02:08PM (2 children)

        by Immerman (3985) on Monday August 26 2019, @02:08PM (#885633)

        I disagree. Const is a valuable modifier that should be applied to any function interface where you're accepting parameters by reference, unless you explicitly intend to modify those parameters.

        Not because it makes code faster. Not even because it guarantees that the parameters won't be changed (it's almost always a bad idea, but you can always cast away const). But because it establishes the contract between function and calling context that the parameters will not be changed. How else are you going to do that? A sentence in the function comments that will almost never be read, and won't invoke any compiler errors to warn you when the contract is broken?

        Not to mention the fact that if your function takes non-const parameters that it never intends to modify, then you've just made it impossible to call with const data. A simple example - you declare a function:
        int CountLetters(char* theString);
        And you can't do something simple like call that function as
        int c = CountLetters("Some String #$ with 7298 letters, spaces, punctuations, etc");

        Put that in a larger context where you might want to call that function from within another function that *does* formally establish the contract and... you can't. Not without casting away const on the big fugly data object your own function asserted it would not modify. When a function fails to assert the constness of its unmodified by-ref parameters, it creates headaches for everyone upstream - forcing them to either leave their own constness unstated, or engage in const-casting.

        >Const is for things like where you would do something like #define XYZ 2....
        It is also handy for declaring constants in that manner, but that's hardly it's primary use

        • (Score: 0) by Anonymous Coward on Monday August 26 2019, @04:28PM (1 child)

          by Anonymous Coward on Monday August 26 2019, @04:28PM (#885696)

          Defining arguments as const is like soldering the RAM on the motherboard. 640k enough for everybody. Pats self on back.

          • (Score: 2) by Immerman on Monday August 26 2019, @04:48PM

            by Immerman (3985) on Monday August 26 2019, @04:48PM (#885703)

            How exactly is promising not to modify the string you asked me to analyze even remotely similar to hard(ware)-limiting resource constraints?

            You expect that a function that has no need to modify its parameters is going to suddenly reach a point where it needs to do so? And more to the point, that you could change it to start modifying its parameters without causing all sorts of unexpected problems in the many places it was called in contexts that assumed it wouldn't?

  • (Score: 4, Insightful) by Anonymous Coward on Sunday August 25 2019, @04:03PM

    by Anonymous Coward on Sunday August 25 2019, @04:03PM (#885218)

    Pointer constness is not about illusion of speed, it is about illusion of safety.

  • (Score: 0) by Anonymous Coward on Sunday August 25 2019, @04:15PM

    by Anonymous Coward on Sunday August 25 2019, @04:15PM (#885222)

    Const makes C faster like speed holes make your car faster.

  • (Score: 3, Interesting) by SemperOSS on Sunday August 25 2019, @04:48PM (8 children)

    by SemperOSS (5072) on Sunday August 25 2019, @04:48PM (#885230)

    I rarely ever use const in my programs, except occasionally as a reminder to myself.

    I recently did some one-on-one C coaching/mentoring of a young man, who had just started university and told him the rationale behind keywords like const and register, the latter being entirely anachronistic these days, really. I am not entirely sure he fully grasped the ingenuity of early computer scientists and programmers, who managed feats like writing compilers for languages such as ALGOL and FORTRAN on a computer with 16kB of core memory.


    --
    I don't need a signature to draw attention to myself.
    Maybe I should add a sarcasm warning now and again?
    • (Score: 1, Funny) by Anonymous Coward on Sunday August 25 2019, @05:07PM (3 children)

      by Anonymous Coward on Sunday August 25 2019, @05:07PM (#885234)

      C, Algol, and Fortran are obsolete languages for old people. Rockstar coders don't use old dead languages for social media marketing. Coding today is about selling an app to a billion idiot users, not about being clever with a computer.

      • (Score: 2) by barbara hudson on Sunday August 25 2019, @07:17PM (2 children)

        by barbara hudson (6443) <barbara.Jane.hudson@icloud.com> on Sunday August 25 2019, @07:17PM (#885318) Journal
        Coding today is all about tracking people to sell ads. If your app doesn't track people as invasively as possible (remember the dildo that could be worked via a smartphone app that sent data to the mother shit?) you are obsolete.

        Speaking of which, WTF is up with getting rid of the "volatile" keyword?

        --
        SoylentNews is social media. Says so right in the slogan. Soylentnews is people, not tech.
        • (Score: 2) by Immerman on Monday August 26 2019, @04:56PM (1 child)

          by Immerman (3985) on Monday August 26 2019, @04:56PM (#885705)

          Say what?!? They're getting rid of volatile? I hadn't heard that, and it's madness. Not that I've used it very often, maybe once every few years, but when it's needed....

          What's the alternative? Especially in a world where multi-threading has become compulsory if you want decent performance. Just assume everything is volatile and eliminate vast swaths of optimizations? Lock anything that might possibly be modified elsewhere behind mutexes? ...I suppose that might actually be good practice in a lot of cases, but I shudder at the thought of the performance penalties it would impose.

    • (Score: 4, Interesting) by bzipitidoo on Sunday August 25 2019, @07:45PM (3 children)

      by bzipitidoo (4388) on Sunday August 25 2019, @07:45PM (#885342) Journal

      I use const all the time. They're a great use of global scope. Making labels for small constants helps distinguish between multiple constants that happen to have the same value.

      As to performance, how about "Pascal" for a now obscure performance related C keyword? Think it was deprecated, maybe in C99.

      • (Score: 5, Funny) by Bot on Sunday August 25 2019, @09:11PM (2 children)

        by Bot (3902) on Sunday August 25 2019, @09:11PM (#885378) Journal

        >I use const all the time
        You mean, like, constantly?

        --
        Account abandoned.
  • (Score: 3, Insightful) by Ken_g6 on Sunday August 25 2019, @05:18PM (13 children)

    by Ken_g6 (3706) on Sunday August 25 2019, @05:18PM (#885243)

    Const function arguments won't make code faster. On the other hand, const constants really should, such as this:

    const int d=4;

    for(int i=0; i < 100; i++) {
        printf("%d\n", i/d);
    }

    i/d should get turned into i>>2.

    • (Score: 2, Insightful) by Anonymous Coward on Sunday August 25 2019, @05:26PM (3 children)

      by Anonymous Coward on Sunday August 25 2019, @05:26PM (#885249)

      JavaScript runs on the consumer end. Nobody gives a shit about how fast it because we don't fucking run it. As long as we get that sweet sweet data to the advertising server so we can sell targeted ads to the fucking idiot consumer. Nothing else matters.

      • (Score: 2) by maxwell demon on Sunday August 25 2019, @08:38PM (2 children)

        by maxwell demon (1608) on Sunday August 25 2019, @08:38PM (#885362) Journal

        And in which way are the properties of JavaScript relevant for the optimization of code written in C or C++?

        --
        The Tao of math: The numbers you can count are not the real numbers.
        • (Score: 1, Funny) by Anonymous Coward on Sunday August 25 2019, @09:25PM (1 child)

          by Anonymous Coward on Sunday August 25 2019, @09:25PM (#885384)

          You're not getting the message, snowflake. C is irrelevant because C is not used in the real world to sell targeted advertising. JavaScript makes money.

          • (Score: 0) by Anonymous Coward on Monday August 26 2019, @11:00AM

            by Anonymous Coward on Monday August 26 2019, @11:00AM (#885592)

            Still mining Monero on other people's computers? Tse, tse.

    • (Score: 2) by BsAtHome on Sunday August 25 2019, @05:38PM

      by BsAtHome (889) on Sunday August 25 2019, @05:38PM (#885259)

      In this *special* case, that would work. But only if you look at the loop variable 'i' and detect it to be strictly positive. Otherwise, shifting does not always act as you want for integers. Not all compilers distinguish between LSR and ASR. Therefore, you would want to use unsigned types, which are more narrowly defined.

      The other problem is that the constant declared integer 'd' has a memory allocation in the strict sense. It is declared non-static and must therefore be visible throughout the link-space as addressable and cannot be eliminated using substitution easily. Referring to 'd' in the code therefore requires a memory dereference.

      That brings us to the problem that you can take the address of 'd' (using &d) and have a (const int *) type. That means that 'd' /must/ be in addressable memory-space and cannot be substituted as a constant value in the division.

      Please note that declaring a 'const int' in your code is not the same as using #define. These are two totally different beasts of constructs with each their advantages and disadvantages. Do not get them mixed up.

    • (Score: 2, Informative) by Anonymous Coward on Sunday August 25 2019, @06:02PM (5 children)

      by Anonymous Coward on Sunday August 25 2019, @06:02PM (#885271)

      Well, let's see. With GCC 8.3.0, you get, (sorry, all the brackets removed, but I can't be arsed to HTML quote them for soylent crappy interface)


            0x0000000000000000 : push %rbp
            0x0000000000000001 : lea 0x0(%rip),%rbp # 0x8
            0x0000000000000008 : push %rbx
            0x0000000000000009 : xor %ebx,%ebx
            0x000000000000000b : sub $0x8,%rsp
            0x000000000000000f : nop
            0x0000000000000010 : mov %ebx,%esi
            0x0000000000000012 : mov %rbp,%rdi
            0x0000000000000015 : xor %eax,%eax
            0x0000000000000017 : add $0x1,%ebx
            0x000000000000001a : sar $0x2,%esi ---- HERE
            0x000000000000001d : callq 0x22
            0x0000000000000022 : cmp $0x64,%ebx
            0x0000000000000025 : jne 0x10
            0x0000000000000027 : add $0x8,%rsp
            0x000000000000002b : pop %rbx
            0x000000000000002c : pop %rbp
            0x000000000000002d : retq

      and without the const,


            0x0000000000000000 : push %rbp
            0x0000000000000001 : lea 0x0(%rip),%rbp # 0x8
            0x0000000000000008 : push %rbx
            0x0000000000000009 : xor %ebx,%ebx
            0x000000000000000b : sub $0x8,%rsp
            0x000000000000000f : nop
            0x0000000000000010 : mov %ebx,%esi
            0x0000000000000012 : mov %rbp,%rdi
            0x0000000000000015 : xor %eax,%eax
            0x0000000000000017 : add $0x1,%ebx
            0x000000000000001a : sar $0x2,%esi --- HERE
            0x000000000000001d : callq 0x22
            0x0000000000000022 : cmp $0x64,%ebx
            0x0000000000000025 : jne 0x10
            0x0000000000000027 : add $0x8,%rsp
            0x000000000000002b : pop %rbx
            0x000000000000002c : pop %rbp
            0x000000000000002d : retq

      Wow, so the same. Actually, not surprised at all. The compiler will determine if something can be changed by some lines of code and it's useless to have const. That's mostly for the programmer, not the compiler.

      • (Score: 0) by Anonymous Coward on Sunday August 25 2019, @08:09PM

        by Anonymous Coward on Sunday August 25 2019, @08:09PM (#885352)

        sorry, all the brackets removed, but I can't be arsed to HTML quote them for soylent crappy interface

        You could have used Unicode brackets instead:[]{}<>

      • (Score: 2) by maxwell demon on Sunday August 25 2019, @09:07PM (3 children)

        by maxwell demon (1608) on Sunday August 25 2019, @09:07PM (#885376) Journal

        For code there is <ecode>:

        Tags are <not> a problem </> if you use the right<tm/> tool for the job.

        Note: I did <em>not</em> encode the tags here (well, except in the line above the <ecode> block).

        --
        The Tao of math: The numbers you can count are not the real numbers.
        • (Score: 0) by Anonymous Coward on Monday August 26 2019, @08:04AM (2 children)

          by Anonymous Coward on Monday August 26 2019, @08:04AM (#885565)

          Good to know <;->

          • (Score: 0) by Anonymous Coward on Monday August 26 2019, @10:53AM (1 child)

            by Anonymous Coward on Monday August 26 2019, @10:53AM (#885590)

            C:/>

            • (Score: 0) by Anonymous Coward on Monday August 26 2019, @09:32PM

              by Anonymous Coward on Monday August 26 2019, @09:32PM (#885817)

              You unix kids and those wrong-way slashes.

    • (Score: 2, Informative) by Anonymous Coward on Sunday August 25 2019, @06:02PM (1 child)

      by Anonymous Coward on Sunday August 25 2019, @06:02PM (#885272)

      Any compiler worth it's salt should be able to identify constants and optimize accordingly regardless of whether they are declared as const or not.

      • (Score: 2) by FatPhil on Monday August 26 2019, @06:12AM

        by FatPhil (863) <pc-soylentNO@SPAMasdf.fi> on Monday August 26 2019, @06:12AM (#885536) Homepage
        Yes, in order to make this an example, it would need to have been an extern that the compiler couldn't know the value of at runtime. Except then all it would do would be a test of avoiding reloads of const externs, not of opcode substututions. And in the absence of a volatile, the const would give the compiler no greater optimising capabilities, so it wouldn't even be an example of that. (And yes, "const volatile" makes perfect sense.)
        --
        Great minds discuss ideas; average minds discuss events; small minds discuss people; the smallest discuss themselves
  • (Score: 2) by hendrikboom on Sunday August 25 2019, @08:23PM (1 child)

    by hendrikboom (1125) Subscriber Badge on Sunday August 25 2019, @08:23PM (#885357) Homepage Journal

    In the original example, it's possible for the argument x to point into variables controlling printf's output buffer, so it'a very possible for *x to change even without calling another function.

    • (Score: 3, Insightful) by FatPhil on Monday August 26 2019, @06:18AM

      by FatPhil (863) <pc-soylentNO@SPAMasdf.fi> on Monday August 26 2019, @06:18AM (#885538) Homepage
      Yeah, a 'restrict' would have made the example better.

      Rather than saying "const didn't help the compiler optimise maximally, so don't bother using const", the article should have been "why doesn't the compiler do the optimisation I wanted?".

      This is an article about how useless cars are for getting you places, in situations where the car is up on bricks.

      Worse - this article hasn't even noticed the bricks.
      --
      Great minds discuss ideas; average minds discuss events; small minds discuss people; the smallest discuss themselves
  • (Score: 3, Insightful) by maxwell demon on Sunday August 25 2019, @08:35PM (3 children)

    by maxwell demon (1608) on Sunday August 25 2019, @08:35PM (#885361) Journal

    I didn't have to look at the compiler output to know that the compiler cannot use const for optimization in this case. Just my general C and C++ knowledge.

    Let's look at the code:

    void constFunc(const int *x);

    void constByArg(const int *x)
    {
      printf("%d\n", *x);
      constFunc(x);
      printf("%d\n", *x);
    }

    So what does this tell the compiler? Well, it tells the compiler that the function constByArg gets a pointer to a potentially constant integer, and that it should not modify that integer through that pointer. It then passes the pointer on to constFunc which makes the same promise.

    However while compiling constByArg, the compiler does not know where the variable comes from, and in particular not whether it is really const, nor whether constFunc can change that variable by other means. For example, another translation unit might contain the following code:

    int var; // NOT const!

    void constFunc(const int *x)
    {
      var++; // legal! Does not attempt to change *x, not even through a typecast
    }

    int main()
    {
      var = 42;
      constByArg(&var);
    }

    That program is 100% legal code, and is required to output

    42
    43

    In other words, if the compiler made the optimizations the author was obviously expecting, it would not conform to the standard.

    But anyway, const isn't even meant as an optimization tool, it is meant as a tool to help with ensuring correctness of code. Just like the compiler will flag as error any attempts to multiply a pointer by 2, even though on about every modern architecture the pointer just contains a number, the compiler will also flag the attempt to modify a value through pointers to const. And just like you can bypass the first error with typecasts, you also can bypass the second error. A typecast is basically telling the compiler "I know what I'm doing, so don't complain". Of course if you do not know what you are doing, your code may blow up. But hey, if you disable the safety mechanisms, that's what you have to expect (just ask the people who operated the Chernobyl reactor!).

    --
    The Tao of math: The numbers you can count are not the real numbers.
    • (Score: -1, Redundant) by Anonymous Coward on Sunday August 25 2019, @11:13PM (1 child)

      by Anonymous Coward on Sunday August 25 2019, @11:13PM (#885412)

      void constFunc(const int *x)
      {
          var++; // legal! Does not attempt to change *x, not even through a typecast
      }

      Assuming you got the function names wrong by accident, and you meant to put in two printfs, no shit? You weren't doing an operation on *x.

      However, if you read *x, a const int *, you would have seen the value change.

      • (Score: 2) by maxwell demon on Sunday August 25 2019, @11:25PM

        by maxwell demon (1608) on Sunday August 25 2019, @11:25PM (#885418) Journal

        I did not get the function names wrong. If you look at the complete post, you'll find the call of constFunc, as well as the two printf calls.

        --
        The Tao of math: The numbers you can count are not the real numbers.
    • (Score: 2) by FatPhil on Monday August 26 2019, @07:51AM

      by FatPhil (863) <pc-soylentNO@SPAMasdf.fi> on Monday August 26 2019, @07:51AM (#885559) Homepage
      Not that you can't create counter-examples without, perhaps we should also be teaching programmers the evils of global variables, so that when the simplest counter-examples such as yours (yet, apparently, too complex for the AC to understand - what is the correct moderation for such a useless post?) are shown the young programmer knows that evil was being invoked during the process of breaking things.

      In order for const to help provide what newbs thinks const provides, you also need to teach them restrict and __attr__((pure)) (and thefore that in order to achieve their goals they need to escape the core language, and rely on individual implementations instead), and then hammer into them the fact that if you do end up with the desired optimisations it's only a side effect of what you've actually concretely got - namely an instruction that *you* are not permitted to alter the pointed-to object (via that pointer, modulo "restrict").

      It was a bad choice of word, and we're stuck with it, but that doesn't mean it's a bad concept, despite what some of the neighsayers are braying on about above.
      --
      Great minds discuss ideas; average minds discuss events; small minds discuss people; the smallest discuss themselves
  • (Score: 2) by darkfeline on Sunday August 25 2019, @09:26PM (1 child)

    by darkfeline (1030) on Sunday August 25 2019, @09:26PM (#885385) Homepage

    One of the nice features of Go is that it has real constants. Consts are analogous to macros in that they are rendered at compile time.

    Some effects of this:

    1. You can't take a pointer to a const, since a const doesn't exist in memory; its literal value is inserted where it's present in the code.
    2. Numeric consts have infinite precision and are unbounded. You can make consts far greater than an int64 for example, and division is exact. Of course, if you try to assign such a const to a variable the value will get truncated.
    3. The compiler can reason about consts, e.g. for pruning branches.

    --
    Join the SDF Public Access UNIX System today!
    • (Score: 0) by Anonymous Coward on Monday August 26 2019, @08:08AM

      by Anonymous Coward on Monday August 26 2019, @08:08AM (#885566)

      One of the nice features of Go is that it has real constants.

      So does C++. They are just called constexpr

      const is from the old days and like everything else legacy, it has history and "reasons". If you want real constants that are not macros, use constexpr.

  • (Score: 2) by cosurgi on Monday August 26 2019, @09:32AM (2 children)

    by cosurgi (272) on Monday August 26 2019, @09:32AM (#885580) Journal

    > can be made slightly faster because the compiler knows that *x is constant

    The compiler knows *x is constant only if you use constexpr [1], and optimizes for that. You will want to repeat all your benchmarks with this small fix. Remember that this works only if the value is known at compile time.

    [1] https://en.cppreference.com/w/cpp/language/constexpr [cppreference.com]

    --
    #
    #\ @ ? [adom.de] Colonize Mars [kozicki.pl]
    #
    • (Score: 2) by turgid on Monday August 26 2019, @10:24AM

      by turgid (4318) Subscriber Badge on Monday August 26 2019, @10:24AM (#885587) Journal

      If you are coding in one of the modern and incredibly complex dialects of C++. C programmers know what they are doing,

    • (Score: 0) by Anonymous Coward on Monday August 26 2019, @04:24PM

      by Anonymous Coward on Monday August 26 2019, @04:24PM (#885691)

      Completely untrue. In this case, const and constexpr will be equivalent.

(1)