138

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Nils Pipenbrinck
  • 83,631
  • 31
  • 151
  • 221
  • Is there a const keyword in C now? There didn't used to be but I'm not so familiar with the C 99 standard. – Onorio Catenacci Oct 02 '08 at 14:15
  • 8
    You don't need to be. C90 is enough. It wasn't in the original K&R C though. – Mark Baker Oct 02 '08 at 14:22
  • 3
    It is a keyword in C89 and ANSI. I don't know if it was a keyword back in the Kerningham and Richie days. – Nils Pipenbrinck Oct 02 '08 at 14:25
  • 8
    This site translates "C gibberish" to English http://www.cdecl.org/ – Motti Apr 28 '10 at 08:35
  • 6
    I'd say "C gibberish to English gibberish", but still nice :) – Kos Dec 15 '10 at 14:31
  • This is an equivalent question with [What is the difference between const int*, const int * const, and int const *?](http://stackoverflow.com/questions/1143262/what-is-the-difference-between-const-int-const-int-const-and-int-const/1143272#1143272) Check it! :) – alandawkins Feb 20 '17 at 03:19

9 Answers9

372

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
Ates Goral
  • 137,716
  • 26
  • 137
  • 190
  • 6
    what about "char const *u"? Does this read "A pointer to a constant character" or "a pointer that is constant to a character"? Seems ambiguous. The standard says the former, but to find this out, you have to take into account the precedence and associativity rules. – Panayiotis Karabassis Jul 01 '12 at 18:24
  • 7
    @PanayiotisKarabassis All should be treated as a chain of adjectives, without swapping any places. `char const *`, read from left-to-right is: "pointer, const, char". It's a pointer to const char. When you say "a pointer that is constant", the "constant" adjective is on the pointer. So, for that case, your list of adjectives should have really been: "const, pointer, char". But you're right, there's ambiguity to this trick. It's really a "trick", more than a definitive "rule". – Ates Goral Jul 02 '12 at 16:42
  • 5
    When you declare a wild combination of array, function, pointer, and function pointer, backwards-reading doesn't work anymore (sadly). However, you can read these messy declarations in a [spiral pattern](http://c-faq.com/decl/spiral.anderson.html). Others were so frustrated by them they invented Go. – Martin J.H. May 20 '14 at 14:14
  • @Martin J.H: Couldn't they be broken up by means of typedefs? And/or using references to eliminate indirections? – Peter Mortensen May 01 '20 at 21:18
203

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

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
15

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;
}
Andru Luvisi
  • 24,367
  • 6
  • 53
  • 66
10

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.

Fred Larson
  • 60,987
  • 18
  • 112
  • 174
5

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.

Emerick Rogul
  • 6,706
  • 3
  • 32
  • 39
5

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.

Community
  • 1
  • 1
Nick Westgate
  • 3,088
  • 2
  • 34
  • 41
3

Yes, they are same for just int

and different for int*

prakash
  • 58,901
  • 25
  • 93
  • 115
3

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
Pat Notz
  • 208,672
  • 30
  • 90
  • 92
  • 6
    You are maybe better off to use the rule "const makes const whatever is left of it". E.g. "int * const foo" makes the pointer "const", because the pointer is left to it. However, you would write the second line "int const * bar", makes the int const, because it is left to it. "int const * const * qux", makes both, the int and the pointer const, because either one is once left to it. – Mecki Dec 23 '10 at 15:10
2

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

const int* cantChangeTheData;
int* const cantChangeTheAddress;
user7545
  • 3,020
  • 4
  • 22
  • 22
  • 2
    Indeed, but int const * is the same as the first, so the order of the int and const doesn't matter, it's just the order of the * and the const that does. – Mark Baker Oct 02 '08 at 14:17