Как мы знаем, значение постоянной переменной является неизменным. Но мы можем использовать указатель постоянной переменной, чтобы изменить его.
#include <iostream>
int main()
{
const int integer = 2;
void* tmp = (void*)&integer;
int* pointer = (int*)tmp;
(*pointer)++;
std::cout << *pointer << std::endl;
std::cout << integer << std::endl;
return 0;
}
вывод этого кода:
3
2
Итак, я путаю то, что я изменил на земле? что значит integer
стоять за?
Изменение const
s не определено. Компилятор может хранить бесплатно const
Значения в частях памяти, доступных только для чтения, выдают ошибку при попытке их изменения (бесплатно, не обязательно).
Неопределенное поведение плохо, нежелательно и его следует избегать. Таким образом, не делайте этого.
PS integer
а также pointer
имена переменных в вашем коде, но не особо хорошие имена.
Вы использовали небезопасные приведения в стиле C, чтобы отбросить постоянство. C ++ не является безопасным языком, поэтому вы можете делать такие безумные вещи, как этот. Это не значит, что вы должны. Фактически, вы вообще не должны использовать приведение в стиле C в C ++ — вместо этого используйте reinterpret_cast, const_cast, static_cast и dynamic_cast. Если вы сделаете это, вы обнаружите, что способ изменить значения const — это использовать const_cast, который в точности соответствует языку.
Это неопределенное поведение. Вывод, который вы получите, зависит от компилятора.
Одним из возможных объяснений такого поведения является следующее.
Когда вы заявляете integer
как константа, и использовать ее в выражении, оптимизации компилятора и заменить ее константным литералом, который вы ей присвоили.
Но фактическое содержание ячейки памяти, указанной &integer
изменено Компилятор просто игнорирует этот факт, потому что вы определили его как константу.
Увидеть Const Correctness в C ++. Обратите внимание на вывод ассемблера чуть выше раздела «Оператор Const_cast» на этой странице.
Вы въезжаете на территорию неопределенного поведения.
Если ты пишешь
void* tmp = &integer;
компилятор выдаст вам ошибку. Если вы написали хороший код C ++ и написали
void* tmp = static_cast<void*>(&integer);
компилятор все равно выдаст вам ошибку. Но вы пошли дальше и использовали незащищенное приведение в стиле C, которое не оставило компилятору другого выбора, кроме как делать то, что вы сказали.
Есть несколько способов, которыми компилятор мог бы справиться с этим, не в последнюю очередь из которых:
Вам нужно посмотреть на созданную сборку, чтобы увидеть, какой вариант предпочитает ваш компилятор, но в конце дня: не делай этого это не определено и это означает, что в следующий раз, когда вы обновите свой компилятор или соберетесь на другой системе или измените настройки оптимизатора, поведение вполне может измениться.
Рассматривать
const char h = 'h';
const char* hello = "hello";
const unsigned char num = 2 * 50 + 2 * 2; // 104 == 'h'
arg -= num; // sub 104, eax
char* ptr = (char*)(&h);
Компилятор может выбрать сохранение «h» специально для целей «ptr», или он может сделать так, чтобы «ptr» указывал на «h» в привет. Или он может выбрать расположение значения 104 в инструкции ‘sub 104, eax’.
Ключевое слово const — просто подсказка для компилятора. Компилятор проверяет, является ли переменная константной или нет, и, если вы измените переменную константой напрямую, компилятор выдаст вам ошибку. Но в хранилище переменных нет механизма защиты константных переменных. Таким образом, операционная система не может знать, какая переменная является константой или нет.