1

Look at this code:

int main() {
    int foo = 0;
    const int *ptr = &foo;
    *ptr = 1; // <-- Error here
    return 0;
}

When compiling, clang gives me an error:

const.c:5:7: error: read-only variable is not assignable

Yes, ptr is const, but foo isn't. Why can't I assign a value to foo?

artm
  • 17,291
  • 6
  • 38
  • 54
nalzok
  • 14,965
  • 21
  • 72
  • 139

2 Answers2

18

You need to differentiate these:

const int *ptr = &foo; // <-- NON-CONST pointer, CONST data.
                       // ptr _can_ point somewhere else, but what it points to _cannot_ be modified.


int * const ptr = &foo; // <-- CONST pointer, NON-CONST data.
                        // ptr _cannot_ point to anywhere else, but what it points to _can_ be modified.

const int * const ptr = &foo; // <-- CONST pointer, CONST data.
                              // ptr _cannot_ point to anywhere else, and what it points to _cannot_ be modified.
artm
  • 17,291
  • 6
  • 38
  • 54
9

const int * is a pointer to an integer constant.

That means, the integer value that it is pointing at cannot be changed using that pointer. Even though the memory where the value is stored, (foo) was declared a normal variable and not const, but the variable you are using to change the value if of type pointer to an integer constant.

Now, you can change the value using foo, but not that pointer.


There is a difference between pointer to an integer constant and constant pointer to an integer.

constant pointer to an integer is defined as int * const. You cannot make the pointer point to some other memory once you have initialized.

pointer to an integer constant is defined as int const * or const int *. You cannot change the value pointed to by the pointer through this pointer itself.


NOTE: Use the standard definition of main()

int main(void) //if no command line arguments.
chqrlie
  • 131,814
  • 10
  • 121
  • 189
Haris
  • 12,120
  • 6
  • 43
  • 70
  • So `const int * ptr` is identical to `int * restrict ptr`? – nalzok Feb 14 '16 at 11:29
  • No, restrict is totally different. Its a way to ell the compiler that the memory will not be accessed by any other pointer or variable. See [this](https://en.wikipedia.org/wiki/Restrict) – Haris Feb 14 '16 at 11:32
  • 1
    @sunqingyao: not at all, `restrict` has a totally separate meaning. It is a promise by the programmer than whatever is accessed by `ptr` is not accessed nor modified by another `restrict` qualified pointer for the duration of the its scope. This is an advanced feature to enable aggressive compiler optimisations, you can ignore it completely at this stage. – chqrlie Feb 14 '16 at 11:33
  • _"pointer to an integer constant is defined as `int * const`. "_ <-- That should say _constant pointer to integer_. – Michael Feb 14 '16 at 11:36
  • @Michael: I fixed it. thank you. – chqrlie Feb 14 '16 at 11:37
  • @chqrlie Sometimes the compiler tells me that const is "discarded" on a variable, what's happening? Where can I found articles about this sort of "discarding"? – nalzok Feb 14 '16 at 11:41
  • 1
    @sunqingyao: the compiler issues a diagnostic that `const` is *discarded* when you assign a `const type *` pointer to an unqualified `type *` or `void *` pointer, either with the assignment operator `=` or by passing the `const` pointer as an argument declared without the `const`. This indicates a risky situation where the data might be modified through the assigned pointer when it was received under the promise that it would not be modified. It invokes undefined behavior if the data itself is `const`. Always `const` qualify pointers that are not used to modify the data. – chqrlie Feb 14 '16 at 11:47
  • Understood now, many thanks! – nalzok Feb 14 '16 at 12:00
  • @chqrlie Is `const int const * const a == int const * const a == const int * const a`? – Spikatrix Feb 14 '16 at 12:07
  • 1
    @CoolGuy: yes in C99: the first `const int const * const a` has 2 `const` qualifiers on the same object, but it is OK as specified in C11 6.7.3p5: *If the same qualifier appears more than once in the same specifier-qualifier-list, either directly or via one or more typedefs, the behavior is the same as if it appeared only once*. Note that this was a change in C99 from C90 where it was a constraint violation: *The same type qualifier shall not appear more than once in the same specifier list or qualifier list, either directly or via one or more typedef s.* – chqrlie Feb 14 '16 at 12:21