'const int' vs. 'int const' as function parameters in C++ and C

C++CConstants

C++ Problem Overview


Consider:

int testfunc1 (const int a)
{
  return a;
}

int testfunc2 (int const a)
{
  return a;
}

Are these two functions the same in every aspect or is there a difference?

I'm interested in an answer for the C language, but if there is something interesting in the C++ language, I'd like to know as well.

C++ Solutions


Solution 1 - C++

The trick is to read the declaration backwards (right-to-left):

const int a = 1; // read as "a is an integer which is constant"
int const a = 1; // read as "a is a constant integer"

Both are the same thing. Therefore:

a = 2; // Can't do because a is constant

The reading backwards trick especially comes in handy when you're dealing with more complex declarations such as:

const char *s;      // read as "s is a pointer to a char that is constant"
char c;
char *const t = &c; // read as "t is a constant pointer to a char"

*s = 'A'; // Can't do because the char is constant
s++;      // Can do because the pointer isn't constant
*t = 'A'; // Can do because the char isn't constant
t++;      // Can't do because the pointer is constant

Solution 2 - C++

const T and T const are identical. With pointer types it becomes more complicated:

  1. const char* is a pointer to a constant char
  2. char const* is a pointer to a constant char
  3. char* const is a constant pointer to a (mutable) char

In other words, (1) and (2) are identical. The only way of making the pointer (rather than the pointee) const is to use a suffix-const.

This is why many people prefer to always put const to the right side of the type (“East const” style): it makes its location relative to the type consistent and easy to remember (it also anecdotally seems to make it easier to teach to beginners).

Solution 3 - C++

There is no difference. They both declare "a" to be an integer that cannot be changed.

The place where differences start to appear is when you use pointers.

Both of these:

const int *a
int const *a

declare "a" to be a pointer to an integer that doesn't change. "a" can be assigned to, but "*a" cannot.

int * const a

declares "a" to be a constant pointer to an integer. "*a" can be assigned to, but "a" cannot.

const int * const a

declares "a" to be a constant pointer to a constant integer. Neither "a" nor "*a" can be assigned to.

static int one = 1;

int testfunc3 (const int *a)
{
  *a = 1; /* Error */
  a = &one;
  return *a;
}

int testfunc4 (int * const a)
{
  *a = 1;
  a = &one; /* Error */
  return *a;
}

int testfunc5 (const int * const a)
{
  *a = 1;   /* Error */
  a = &one; /* Error */
  return *a;
}

Solution 4 - C++

Prakash is correct that the declarations are the same, although a little more explanation of the pointer case might be in order.

"const int* p" is a pointer to an int that does not allow the int to be changed through that pointer. "int* const p" is a pointer to an int that cannot be changed to point to another int.

See https://isocpp.org/wiki/faq/const-correctness#const-ptr-vs-ptr-const.

Solution 5 - C++

const int is identical to int const, as is true with all scalar types in C. In general, declaring a scalar function parameter as const is not needed, since C's call-by-value semantics mean that any changes to the variable are local to its enclosing function.

Solution 6 - C++

They are the same, but in C++ there's a good reason to always use const on the right. You'll be consistent everywhere because const member functions must be declared this way:

int getInt() const;

It changes the this pointer in the function from Foo * const to Foo const * const. See here.

Solution 7 - C++

Yes, they are same for just int

and different for int*

Solution 8 - C++

This isn't a direct answer but a related tip. To keep things straight, I always use the convection "put const on the outside", where by "outside" I mean the far left or far right. That way there is no confusion -- the const applies to the closest thing (either the type or the *). E.g.,




int * const foo = ...; // Pointer cannot change, pointed to value can change
const int * bar = ...; // Pointer can change, pointed to value cannot change
int * baz = ...; // Pointer can change, pointed to value can change
const int * const qux = ...; // Pointer cannot change, pointed to value cannot change

int * const foo = ...; // Pointer cannot change, pointed to value can change const int * bar = ...; // Pointer can change, pointed to value cannot change int * baz = ...; // Pointer can change, pointed to value can change const int * const qux = ...; // Pointer cannot change, pointed to value cannot change

Solution 9 - C++

I think in this case they are the same, but here is an example where order matters:

const int* cantChangeTheData;
int* const cantChangeTheAddress;

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNils PipenbrinckView Question on Stackoverflow
Solution 1 - C++Ates GoralView Answer on Stackoverflow
Solution 2 - C++Konrad RudolphView Answer on Stackoverflow
Solution 3 - C++Andru LuvisiView Answer on Stackoverflow
Solution 4 - C++Fred LarsonView Answer on Stackoverflow
Solution 5 - C++Emerick RogulView Answer on Stackoverflow
Solution 6 - C++Nick WestgateView Answer on Stackoverflow
Solution 7 - C++prakashView Answer on Stackoverflow
Solution 8 - C++Pat NotzView Answer on Stackoverflow
Solution 9 - C++user7545View Answer on Stackoverflow