Хотелось бы понять, как С++ обрабатывает константы базовых типов. Что будет, если при помощи плясок с бубном и указателями изменить значение, находящееся в ячейке памяти, где, по идее, и должна содержаться константа? Есть следующий код: #include using namespace std int main(int argc, char** argv) { const int number = 45 const int * constPoint = &number cout << "constPoint " << constPoint << endl int * point = (int *) constPoint cout << " point " << point << endl * point = 54 cout << "&number " << &number << " number " << number << endl cout << " point " << point << " *point " << *point << endl } <br>Вывод у меня получается следующий: constPoint 0x7fff1b73a6ec point 0x7fff1b73a6ec &number 0x7fff1b73a6ec number 45 point 0x7fff1b73a6ec *point 54 Таким образом, значение константы не изменилось, хотя число, которое содержится в ячейке по адресу этой константы, уже другое. Как объяснить подобное поведение? Я не собираюсь такой код никогда использовать на практике, просто хочу понять, где хранятся константы.
Ответ Для начала: по стандарту, изменение при помощи трюков с указателями констант есть undefined behaviour. Может случится всё, что угодно в любой точке программы. Компилятор имеет право не хранить константу вообще нигде, если вы к ней не обращаетесь. Или имеет право хранить, если ему покажется так лучше. Или хранить в памяти только для чтения. Или хранить по общему адресу с какой-нибудь инструкцией кода, которая численно равна этой же константе. Например, если компилятор видит обращение к константе, он может встроить её в точку вызова (он ведь знает значение на этапе компиляции), может обратиться к этой константе по адресу в любой момент, может даже выразить другие константы через эту (например, если у вас есть константа 1024, то обращение к 2048 он имеет право представить как 1024 << 1 из соображений эффективности).<br>Хуже того, если где-то компилятор выяснил для себя, что константа чётная, и её младший бит равен 0, и на основании этой информации смог исключить какие-нибудь проверки из кода, то теперь проверки не пройдут, и код может крешнуться в любой момент. На UB обычно основаны дыры в безопасности программ. Например, если компилятор обоснованно считает, что длина строки 45, и под неё достаточно выделить буфер такой длины, в то время как вы, обманув компилятор, подсунете ему строку длиной 54, получится классический срыв стека.
Резюме: У компилятора нет никаких «обязательств» или «принципов» по работе с константами. Он имеет право делать что угодно. Наоборот, это программист, если уж обещал, что какое-то значение есть константа, не имеет права его менять.