Подтвердить что ты не робот

Можем ли мы изменить значение объекта, определенного с помощью const через указатели?

#include <stdio.h>
int main()
{
    const int a = 12;
    int *p;
    p = &a;
    *p = 70;
}

Будет ли это работать?

4b9b3361

Ответ 1

Это "undefined поведение", что означает, что на основе стандарта вы не можете предсказать, что произойдет, когда вы попробуете это. Он может делать разные вещи в зависимости от конкретной машины, компилятора и состояния программы.

В этом случае наиболее часто случается, что ответ будет "да". Переменная const или нет - это просто место в памяти, и вы можете нарушать правила константы и просто перезаписывать ее. (Конечно, это вызовет серьезную ошибку, если какая-либо другая часть программы зависит от постоянных константных данных!)

Однако в некоторых случаях - наиболее типично для данных const static - компилятор может помещать такие переменные в область памяти только для чтения. Например, MSVC обычно ставит константные статические ints в сегменте .text исполняемого файла, что означает, что операционная система будет вызывать ошибку защиты, если вы попытаетесь записать на нее, и программа выйдет из строя.

В какой-то другой комбинации компилятора и машины может произойти нечто совершенно другое. Единственное, что вы можете точно предсказать, это то, что этот шаблон будет раздражать тех, кто должен прочитать ваш код.

Ответ 2

Это поведение undefined. Доказательство:

/* program.c */

int main()
{
        const int a = 12;
        int* p;
        p = &a;
        *p = 70;
        printf("%d\n", a);
        return 0;
}


gcc program.c

и запустите его. Выход будет равен 70 (gcc 4.3)

Затем скомпилируйте его следующим образом:

gcc -O2 program.c

и запустите его. Выход будет 12. Когда он делает оптимизацию, компилятор предположительно загружает 12 в регистр и не утруждает себя повторной загрузкой, когда ему нужно получить доступ к a для printf, потому что он "знает", что не может измениться.

Ответ 3

Изменение квалифицированного объекта const через указатель вызывает неопределенное поведение, и таков результат. Это может быть то, что вы ожидаете от конкретной реализации, например, предыдущее значение без изменений, если оно было помещено в .text и т.д.

Ответ 4

Это действительно работает с gcc. Это ему не понравилось, хотя:

test.c: 6: warning: присваивание отбрасывает квалификаторы из целевого типа указателя

Но значение изменилось при выполнении. Я не буду указывать на очевидное нет-нет...

Ответ 5

да, вы можете сделать это, используя такой код. но код не применяется, когда a является глобальным (gcc-скомпилированная программа дала мне segmentation fault.)

вообще, в любимом C, вы почти всегда можете найти что-то, чтобы взломать вещи, которые не должны быть изменены или выставлены. const здесь является примером.

Но размышление о бедном парне (может быть, мне через 6 месяцев) поддерживает наш код, я часто предпочитаю не делать этого.

Ответ 6

Здесь тип указателя p равен int*, которому присваивается значение типа const int* (&a = > адрес переменной const int).

Неявный бросок исключает константу, хотя gcc выдает предупреждение (обратите внимание, что это во многом зависит от реализации).

Так как указатель не объявлен как const, значение может быть изменено с помощью такого указателя.

если указатель будет объявлен как const int* p = &a, вы не сможете сделать *p = 70.

Ответ 7

Вы не можете изменить значение константы с помощью указателя, указывающего на него. Этот тип указателя называется Pointer to a constant.

Существует также другое понятие под названием Constant Pointer. Это означает, что, как только указатель указывает на ячейку памяти, вы не можете указать ее на другое местоположение.

Ответ 8

Плохая идея BAD.

Кроме того, поведение зависит от платформы и реализации. Если вы работаете на платформе, где константа хранится в незаписываемой памяти, это явно не сработает.

И, зачем же вы хотите? Либо обновите константу в своем источнике, либо сделайте ее переменной.

Ответ 9

Этот код содержит нарушение ограничений:

const int a = 12;
int *p;
p = &a;

Нарушением является C11 6.5.16.1/1 "Простое присвоение"; если оба операнда являются указателями, то тип, на который указывает левый, должен иметь все определители типа, на который указывает справа. (И типы, не имеющие квалификаторов, должны быть совместимы).

Таким образом, ограничение нарушается, потому что &a имеет тип const int *, который имеет const как квалификатор; но этот определитель не отображается в типе p который является int *.

Компилятор должен испускать диагностику и не может генерировать исполняемый файл. Поведение любого исполняемого файла полностью не определено, так как программа не соответствует правилам языка.

Ответ 10

Да, вы можете изменить значение постоянной переменной.
Попробуйте этот код:

#include <stdio.h>

int main()
{
    const  int x=10;

    int *p;
    p=(int*)&x;
    *p=12;
    printf("%d",x);
}