8

I do understand the meaning of const for pointers or structures that have to be passed by reference to a function. However in the example:

void foo(const int a);

the variable a is passed on the stack. There is no harm to the caller to modify the content of the stack so const looks pretty useless in this situation.

Furthermore, if I cannot modify a, I can still make a copy of a and change this copy:

void foo(const int a)
{
   int b = a;
   b++;
}

In which situation does the const keyword will be useful when applied to a scalar function argument (not a pointer)?

nowox
  • 25,978
  • 39
  • 143
  • 293
  • Just because something can be done doesn't mean it should be done or is useful. In this case, as the others have stated, it might be useful. – Transcendental Apr 12 '16 at 14:28

5 Answers5

4

Code like void foo(const int a) is not really meaningful, nor is it "const correctness" as such.

Sometimes overly pedantic programmers get the weird idea that they need to declare common parameters as const just because a function doesn't modify the actual parameter. But most often, functions do not.

The point is, the variable is a copy of the original, so what your function does with it doesn't matter the slightest!

So this is not even a way of writing self-documenting code, because all it does is to tell the caller what's going on internally inside your function. The caller doesn't care and shouldn't care.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • 2
    I personally use `const` qualifier for function parameters a lot -- basically every time I do not need to modify the parameter in the function body at all. It used to help some C compilers to generate better code, but that is not why I do it. I do it because it helps when humans read the code. Instead of carefully reading through a function to see if the value gets changed, the `const` lets us safely assume it stays as the value specified by the caller. That is why I integrated it into my coding style. If that is *overly pedantic*, well, so be it. – Nominal Animal Apr 12 '16 at 17:57
  • @NominalAnimal It doesn't help humans read the code if it is in the function prototype. It has absolutely no meaning there. – juanchopanza Apr 13 '16 at 06:03
  • @NominalAnimal I very much doubt it ever helped any compiler to generate better code (unlike`restrict` etc). Also, if you have to slowly and carefully read through a function to tell if a variable is modified, then likely that function needs to be split up in several. – Lundin Apr 13 '16 at 06:37
3

It's unnecessary to use const for a value parameter, but it has its value if what you want is to guarantee the code does what you intend.

Here there's an answer with some example of use cases

Community
  • 1
  • 1
dfranca
  • 5,156
  • 2
  • 32
  • 60
2

It means that an implementer of the function cannot change the value of the input parameter a that the function receives by value.

It can lead to increased program stability.

(Personally I dislike the style as I find it too verbose).

If you do adopt this style, then note well that you only need to put the const in the parameter list of the function definition, you don't need it in the declaration.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • The value is passed on the stack. By definition the implementer cannot change the value of `a`. – nowox Apr 12 '16 at 14:28
  • In a sense yes, but the value of `a` cannot be changed by the function. – Bathsheba Apr 12 '16 at 14:28
  • 3
    "It can lead to increased program stability" How? – Lundin Apr 12 '16 at 14:30
  • 3
    I've seen naughty code like `a /= 100` at least a couple of times. The young quant says "but I need it as a percentage". "No you don't" says I. And to enforce that, here's a `const` in the prototype. Please take the optimisation parameters at face value." There is, by the way, at least one investment bank that *insists* on the `const` style. – Bathsheba Apr 12 '16 at 14:32
  • @Bathsheba The very same problem exists with people abusing floating point numbers because they "need decimals". There are several solutions, none of them involving the `const` keyword: educate people, do code reviews, or don't hire beginners to write high-integrity software to begin with. – Lundin Apr 12 '16 at 14:43
  • @nowox The implementer cannot change the value of the local `a` in the implementation. Just like saying `const int n = 3;` – juanchopanza Apr 12 '16 at 14:44
  • 2
    It might be worth mentioning that it is irrelevant whether the function declaration has a `const` in it or not. What matters is the definition. – juanchopanza Apr 12 '16 at 14:47
  • @juanchopanza: that's a good point. I've added it. My previous comment about the "`const` in the prototype" is imprecise. – Bathsheba Apr 12 '16 at 14:50
  • FWIW, I usually recommend *not* to put the `const` in the declaration, because it can be misleading: the definition can omit it the `const`, and why should the caller care if the implementation doesn't modify one of its local variables anyway? – juanchopanza Apr 12 '16 at 14:55
  • But then again, MISRA for example requires to have the same type qualifiers on declaration and definition. If you want the `const`, and want to comply with MISRA, you should put it in both :S – atturri Apr 12 '16 at 14:57
  • @atturri Does MISRA really require that top level `const`s (which are ignored) match? That would be disappointing. – juanchopanza Apr 12 '16 at 14:59
  • I quote: "The types of the parameters and return values in the prototype and the definition must match. This requires identical types including typedef names and qualifiers, and not just identical base types". I guess the `const` is included in the qualifiers part. – atturri Apr 12 '16 at 15:01
2

It's the same thing as declaring any constant variable

const int size = some_other_variable + 5;

It is a good programming practice to declare variables as const if you know their values will not change. That way from declaration you can avoid that someone accidentally changes their value further down the function.

atturri
  • 1,133
  • 7
  • 13
1

It's useful mostly for purposes of self-documenting your code.

For future people looking through your source code, the const serves to emphasize your intent (that none of the code in foo() should attempt to modify a).

Christian Henry
  • 172
  • 1
  • 5
  • Why would "people" (the caller) care about how your function is implemented internally? That's none of their business and they couldn't care less. – Lundin Apr 12 '16 at 14:37
  • "people" could also be a mantainer of the code. – atturri Apr 12 '16 at 14:38
  • It can only serve to document the *implementation*. It is ignored in the function declaration. – juanchopanza Apr 12 '16 at 14:43
  • @atturri So in case the maintainer of the code has no clue what their own code does, it is there to save them from themselves? Programming doesn't work that way: at the point where you no longer know what your own code does, there is no hope of saving the program. – Lundin Apr 12 '16 at 14:47
  • @Lundin It doesn't have to be your own code. It can be the code of a programmer who left the company 10 years ago without leaving a design document behind. As the answer says, that `const` can serve to emphasize your intent for later readers. – atturri Apr 12 '16 at 14:51
  • @atturri Or alternatively, it can confuse the heck out of future readers. Here, maintain this, I helped you with some self-documenting code to make it more readable and explicit: `extern const signed int func (const signed int x) { auto const signed int y = x + (const signed int)5; return (const signed int)y; }` – Lundin Apr 12 '16 at 15:03
  • @Lundin Okay, seriously? There's a **huge** difference between simply telling future maintainers to expect the passed-in parameter to *not* change in the implementation, and going "hog-wild" with *implied* syntax. Don't forget, any reasonable compiler should yell at you if you (in the implementation) attempt to modify the parameter. – Christian Henry Apr 12 '16 at 16:03
  • @ChristianHenry Note that this will only happen if the `const` is in the implementation. It has no meaning to put it in the function declaration because it gets discarded. So it would mean "the function implementation cannot modify the parameter *iff* it also declares it as `const`", which isn't so useful. Maybe you meant to imply this, but it isn't clear in your answer. – juanchopanza Apr 13 '16 at 06:06
  • @ChristianHenry I really don't see the difference. I don't want to make the function local scope by mistake, so I use extern. I don't want to modify the returned value by mistake, so I make it const. I don't want to use unsigned integers by mistake so I make them signed. And so on. But of course, if you actually know what you are doing, then none of it is needed. – Lundin Apr 13 '16 at 06:33