cconstants

Why is it allowed for a const pointer to be passed as non-const argument of a function and get modified?


I am able to pass a const pointer as argument of a function that takes non-const pointer.

Furthermore, inside the function body, I was allowed to modify its value as well with only a warning:
(passing argument 1 of 'modifyValue' discards 'const' qualifier from pointer target type [-Wdiscarded-qualifiers])
from the compiler but no error.

#include <stdio.h>

void modifyValue(int *ptr) {
    *ptr = 10; // This modifies the value pointed to by ptr
}

int main() {
    const int value = 5;
    const int *constPtr = &value;

    // This doesn't cause a compilation error
    modifyValue(constPtr);
    printf("%d",*constPtr);
    return 0;
}

demo

Is this behavior consistent with C spec? I would have assumed one could not pass const value as non-const argument as it strips away the const-ness. What is the point of the const qualifier if you can pass it through a function and change the value all the same?


Solution

  • Because C gives you enough rope to shoot yourself in the foot ^ACM.

    I think the warning errors are enough:

    ~ » clang main.c                                                                                                                                                                                                                                                            
    main.c:12:17: warning: passing 'const int *' to parameter of type 'int *' discards qualifiers [-Wincompatible-pointer-types-discards-qualifiers]
       12 |     modifyValue(constPtr);
          |                 ^~~~~~~~
    main.c:3:23: note: passing argument to parameter 'ptr' here
        3 | void modifyValue(int *ptr) {
          |                       ^
    1 warning generated.
    
    » gcc main.c
    main.c: In function ‘main’:
    main.c:12:17: warning: passing argument 1 of ‘modifyValue’ discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
       12 |     modifyValue(constPtr);
          |                 ^~~~~~~~
    main.c:3:23: note: expected ‘int *’ but argument is of type ‘const int *’
        3 | void modifyValue(int *ptr) {
          |                  ~~~~~^~~
    

    Try running with -Werror

    ~ » clang -Werror main.c                                                                                                                                                                                                                                                    
    main.c:12:17: error: passing 'const int *' to parameter of type 'int *' discards qualifiers [-Werror,-Wincompatible-pointer-types-discards-qualifiers]
       12 |     modifyValue(constPtr);
          |                 ^~~~~~~~
    main.c:3:23: note: passing argument to parameter 'ptr' here
        3 | void modifyValue(int *ptr) {
          |                       ^
    1 error generated.
    
    ~ » gcc -Werror main.c                                                                                                                                                                                                                                                      
    main.c: In function ‘main’:
    main.c:12:17: error: passing argument 1 of ‘modifyValue’ discards ‘const’ qualifier from pointer target type [-Werror=discarded-qualifiers]
       12 |     modifyValue(constPtr);
          |                 ^~~~~~~~
    main.c:3:23: note: expected ‘int *’ but argument is of type ‘const int *’
        3 | void modifyValue(int *ptr) {
          |                  ~~~~~^~~
    cc1: all warnings being treated as errors