Можем ли мы изменить значение объекта, определенного с помощью const через указатели? - PullRequest
26 голосов
/ 27 сентября 2010
#include <stdio.h>
int main()
{
    const int a = 12;
    int *p;
    p = &a;
    *p = 70;
}

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

Ответы [ 10 ]

30 голосов
/ 27 сентября 2010

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

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

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

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

13 голосов
/ 27 сентября 2010

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

/* 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 в регистр и не удосуживается загрузить его снова, когда ему нужно получить доступ к printf, потому что он «знает», что невозможно изменить. 1009 *

10 голосов
/ 27 сентября 2010

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

5 голосов
/ 27 сентября 2010

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

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

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

3 голосов
/ 27 сентября 2010

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

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

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

1 голос
/ 27 сентября 2010

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

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

Поскольку указатель не объявлен как const, значение можно изменитьиспользуя такой указатель.

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

0 голосов
/ 15 мая 2018

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

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

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

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

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

0 голосов
/ 14 сентября 2017

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

#include <stdio.h>

int main()
{
    const  int x=10;

    int *p;
    p=(int*)&x;
    *p=12;
    printf("%d",x);
}
0 голосов
/ 27 сентября 2010

Плохо, ПЛОХАЯ идея.

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

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

0 голосов
/ 27 сентября 2010

Вы не можете изменить значение постоянной переменной, используя указатель на нее.Указатель этого типа называется Pointer to a constant.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...