Home > OS >  Why the value of a pointer to int can't be the value of a pointer to a const int?
Why the value of a pointer to int can't be the value of a pointer to a const int?

Time:02-28

Why is this incorrect? The problem is when assigning b = p I get the following warning: assignment discards 'const' qualifiers from pointer target type.

int a = 4;
int *b;
const int *p = &a;
b = p;

CodePudding user response:

You have one pointer which is defined to point to an int which you allow to be changed, b; but you do not init it at first.

Then you introduce a pointer to an int which you do not allow to be changed.
And you point it to an existing int. I.e. "Look at that int, but don't you change it."

Then you try to assign the "don't touch this" pointer value to the "hey, have an int, do with what you like" pointer.
The compiler tells you that you are inconsistent there, that you are contradicting yourself and cannot really mean what you write into your code.

That is why it is incorrect. Because you violate the rules which you yourself wrote.

CodePudding user response:

p is a pointer to a constant int and you're assigning it to a pointer to a non-constant int.

CodePudding user response:

p is defined as a const pointer to int, which means it cannot be used to modify the int it points to. You can initialize it from the address of an int that can be modified or not. Conversely, b is a pointer to int that can be used to modify the int it points to. It should only be initialized from a pointer to int with the same ability or the address of an int that is modifiable. b = p violates this constraint, hence the warning.

Note that b = &a is OK as a is modifiable and p = b is OK too, only restricting p from being used to modify a.

You could attempt to silence the warning by casting p as (int *)p but it is not recommended: in this particular instance, p does point to an int that can be modified, but bypassing the const validation by the compiler makes the code less readable and more error prone.

Qualifying p as const int *p is a promise telling I shall not use p to modify what it points to. The need to break this promise is an indication that something is not properly structured in the program.

There is no recommended way to silence this warning, but you can simply change the code to initialize b from &a this way:

int a = 4;
int *b = &a;
const int *p = b;

With the posted order, you could casually write b = (int *)p; to try and silence the warning, but a good compiler such as clang with warnings enabled will still rightfully warn you that this cast is fishy...

If you really need to remove the constness and want to silence the warning that still occurs with the obvious b = (int *)p;, you could write this:

b = (int *)(uintptr_t)(const void *)p;  // avoid this!

CodePudding user response:

assignment discards 'const' qualifiers from pointer target type

The above warning clearly indicates that assignment operator(=) ignores const. This is because b is a pointer to non-const int, whereas p is pointer to const int. You can type-cast p to (int *) to remove that warning like:

b = (int *)p;

As some has suggested typecasting is not recommended but can be used to silence the warning. But if you see the disassembly you will found that typecasting doesn't change anything.

main:
    push    rbp
    mov     rbp, rsp
    mov     DWORD PTR [rbp-20], 4
    lea     rax, [rbp-20]
    mov     QWORD PTR [rbp-8], rax  ;; same with/without typecasting
    mov     rax, QWORD PTR [rbp-8]  ;; same as well
    mov     QWORD PTR [rbp-16], rax
    mov     eax, 0
    pop     rbp
    ret

TRY (TYPE_CASTING)

TRY (NO TYPE_CASTING)

  •  Tags:  
  • c
  • Related