C++ Преобразование из const int* в int *, работающее с неожиданными результатами
В C++ мы знаем, что мы не можем конвертировать const int * в int *. Но у меня есть фрагмент кода, где я могу конвертировать const int * в int *. Я новичок в C++, я гуглил по этому поводу, но я только что получил ссылки с упоминанием const int *, которые нельзя преобразовать в int *, чтобы избежать нарушения const. Я не могу понять, почему он компилируется без ошибок
#include <iostream>
using namespace std;
int main(void)
{
const int a1 = 40;
const int* b1 = &a1;
int* c1 = (int *)(b1);
*c1 = 43;
cout<< c1<<" "<< &a1<<endl;
cout<< *c1<<" "<< a1<<endl;
}
Также проблема в выводе вышеприведенной программы:
0x7fff5476db8c 0x7fff5476db8c
43 40
Может кто-нибудь объяснить, почему целочисленный указатель c1 указывает на один и тот же адрес для a1, но имеет разные значения 43 и 40 соответственно.
4 ответа
В C++ объект является постоянным или нет. Если он постоянный, то любая попытка его изменения вызовет неопределенное поведение. Это то, что ты сделал. В этот момент все может случиться. Если вам повезет, он падает. Если вам повезет меньше, он будет работать до тех пор, пока ваш код не окажется в руках клиента, где он нанесет максимально возможный ущерб.
Вы можете легко преобразовать const int* в int * в C++. Ты только что сделал. Однако "const int*" и "int*" не означают, что указанная вещь является константной или нет. Это просто означает, что компилятор не позволит вам назначить в одном случае, и позволит вам назначить в другом случае. *c1
является const
, Приведение указателя к int*
не меняет того факта, что это const
, Неопределенное поведение.
Это неопределенное поведение.
Но в этом случае произошло то, что компилятор понял, что он может заменить a1
в cout
заявление с фактическим значением 40, потому что это должно быть const
,
Никогда, никогда не полагайтесь на это, хотя. Это могло бы легко нанести татуировку вашей кошке.
const int
переменная будет занимать память в стеке, но компилятор просто заменит весь экземпляр a1
с 40
, Выражение &a1
не заменится, и как-то магическим образом указать на память в стеке. При изменении содержимого содержимое в памяти будет изменяться, но эти константы 40
не изменится. Следовательно, они отличаются по выходу.
Это не что иное, как неопределенное поведение и может отличаться от компилятора. Один компилятор может вызвать 43
для отображения, другой всегда может отображать 40
и некоторые другие могут генерировать код, вызывающий сбой (запись в постоянную память). Не делай этого!
Запустите это, может быть, это поможет.
const int a1 = 40;
std::cout<<"__________ const int a1 = 40; ____________________________________"<<std::endl;
std::cout<<"a1: "<< a1<<std::endl;
std::cout <<"&a1 "<< &a1<<std::endl;
std::cout <<"*a1: INVALID"<<std::endl;
const int* b1 = &a1;
std::cout<<"__________ const int* b1 = &a1; ____________________________________"<<std::endl;
std::cout<<"b1: "<< b1<<std::endl;
std::cout <<"&b1 "<< &b1<<std::endl;
std::cout <<"*b1 "<< *b1<<std::endl;
int* c1 = (int *)(b1);
std::cout<<"__________ int* c1 = (int *)(b1); ____________________________________"<<std::endl;
std::cout<<"c1: "<< c1<<std::endl;
std::cout <<"&c1 "<< &c1<<std::endl;
std::cout <<"*c1 "<< *c1<<std::endl;
*c1 = 43;
std::cout<<"__________ *c1 = 43; ____________________________________"<<std::endl;
std::cout<<"c1: "<< c1<<std::endl;
std::cout <<"&c1 "<< &c1<<std::endl;
std::cout <<"*c1 "<< *c1<<std::endl;
std::cout<<"c1: "<< c1<<std::endl;
std::cout<<"*c1: "<< *c1<<" -----> *&a1: "<< *&a1<<" - a1: "<< a1<<std::endl;
std::cout<<"&c1: "<< &c1<<std::endl;