'const int' vs. 'int const' as function parameters in C++ and C [duplicate]
Asked Answered
D

9

142

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.

Decane answered 2/10, 2008 at 14:11 Comment(6)
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.Jadeite
You don't need to be. C90 is enough. It wasn't in the original K&R C though.Rattlebox
It is a keyword in C89 and ANSI. I don't know if it was a keyword back in the Kerningham and Richie days.Decane
This site translates "C gibberish" to English cdecl.orgRingdove
I'd say "C gibberish to English gibberish", but still nice :)Cummings
This is an equivalent question with What is the difference between const int*, const int * const, and int const *? Check it! :)Simulator
K
207

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

Kulsrud answered 2/10, 2008 at 14:14 Comment(9)
C does have const, given: static const char foo[] = "foo"; you better not alter foo.Burgee
K&R C didn't have const; C90 (and C99) does. It's a bit limited compared to C++, but it is useful.Rattlebox
is this also true for references?Teasley
@Teasley Yes, it's the same.Kulsrud
Is const char* the same as char const* or the same as char* const?Cassiodorus
@étale-cohomology Good point, added. Should have been there all along.Kulsrud
@KonradRudolph so basically any permutation of the following int static unsigned const would yield the same result. i.e. the permutation of the variable definition properties yields the same result as long as no pointers are present. Is this true?Mainstream
How about references? are const T& and T const& equivalent?Drucilladrucy
@Drucilladrucy Yes, same parsing rules as for pointers.Kulsrud
P
375

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
Pectoralis answered 2/10, 2008 at 14:32 Comment(4)
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.Eu
@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".Pectoralis
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. Others were so frustrated by them they invented Go.Koan
@Martin J.H: Couldn't they be broken up by means of typedefs? And/or using references to eliminate indirections?Lighthearted
K
207

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

Kulsrud answered 2/10, 2008 at 14:14 Comment(9)
C does have const, given: static const char foo[] = "foo"; you better not alter foo.Burgee
K&R C didn't have const; C90 (and C99) does. It's a bit limited compared to C++, but it is useful.Rattlebox
is this also true for references?Teasley
@Teasley Yes, it's the same.Kulsrud
Is const char* the same as char const* or the same as char* const?Cassiodorus
@étale-cohomology Good point, added. Should have been there all along.Kulsrud
@KonradRudolph so basically any permutation of the following int static unsigned const would yield the same result. i.e. the permutation of the variable definition properties yields the same result as long as no pointers are present. Is this true?Mainstream
How about references? are const T& and T const& equivalent?Drucilladrucy
@Drucilladrucy Yes, same parsing rules as for pointers.Kulsrud
H
16

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;
}
Hazing answered 2/10, 2008 at 14:28 Comment(0)
F
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.

Footie answered 2/10, 2008 at 14:18 Comment(0)
F
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.

Fulgurous answered 5/11, 2008 at 18:11 Comment(0)
S
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.

Squatness answered 22/9, 2015 at 22:16 Comment(2)
This is a completely different kind of const.Impotent
Yes, the question is about the difference between "const int" and "int const" your answer has nothing to do with it.Impotent
A
3

Yes, they are same for just int

and different for int*

Aceto answered 2/10, 2008 at 14:13 Comment(1)
(const int *) and (int const *) are the same, they are just different from (int *const).Burgee
A
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
Agricola answered 2/10, 2008 at 15:20 Comment(1)
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.Immanuel
P
2

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

const int* cantChangeTheData;
int* const cantChangeTheAddress;
Procopius answered 2/10, 2008 at 14:15 Comment(1)
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.Rattlebox

© 2022 - 2024 — McMap. All rights reserved.