简体   繁体   中英

Why can I modify the const pointer in C?

Today I tried to use const indentifier, but I find the const variable can still be modified, which confuses me..

Following is the code, in compare(const void *a, const void *b) function, I tried to modify the value that a is pointing to:

#include <stdio.h>
#include <stdlib.h>

int values[] = {40, 10, 100, 90, 20, 25};

int compare (const void *a, const void*b)
{
    *(int*)a=2;
/* Then the value that a points to will be changed! */
    return ( *(int*)a - *(int*)b);
}

int main ()
{
    int n;
    qsort(values, 6, sizeof(int), compare);
    for (n = 0; n < 6; n++)
        printf("%d ", values[n]);
    return 0;
}

Then I also tried to change the value of a itself:

#include <stdio.h>
#include <stdlib.h>

int values[] = {40, 10, 100, 90, 20, 25};

int compare (const void *a, const void*b)
{
    a=b;
    return ( *(int*)a - *(int*)b);
}

int main ()
{
    int n;
    qsort(values, 6, sizeof(int), compare);
    for (n = 0; n < 6; n++)
        printf("%d ", values[n]);
    return 0;
}

However, I found both of them works.. Can anyone explain to me why I need to use const in the parameter list of compare if they can still be changed?

It only works in this case because the pointer you're working against wasn't originally constant. Casting away constness and then modifying a value is undefined behaviour. UB means that the app can do anything from succeed to crash to make purple dragons fly out of your nostrils.

Its protecting you from silly mistakes, not when you try hard to make a mistake.
(int *)a when a is const something * is a bad practice, use (const int *)a instead.
a = b when a is const void * is ok because only the value pointed to is const. if you want both *a = x and a = x disallowed, declare a as const void * const .

Case 1: You are using a static cast to cast away the constness. You are violating the contract that was defined for the method.

Case 2: You are not changing the contents of a (which is const), but assigning the variable a which contains a const void pointer.

For practical implications: With case 1.) you could shoot yourself in the foot, in case a was not really pointing to a variable.

Suggestion: Cast away constness only if you know what you are doing.

Actually.

int compare (const void *a, const void*b);

Here there are 2 things you need to consider, the pointer and the memory location that the pointer is pointing to. The pointer is not constant but the memory location is.

If you would change the signature to:

int compare (const void *const a, const void *const void);

Then everything would be const. In your case you can change the pointer but not the value. So that your pointer can point to a different memory location.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM