Typecasted указатель C ++ и не Typecasted указатель указывает на то же место, но дает разные значения - PullRequest
0 голосов
/ 23 февраля 2019

В следующем коде

#include <string.h> 
#include <iostream> 
using namespace std; 

int main() 
{ 
    int *a;
    const int b=5;
    a=(int *)&b;
    *a=6;
    cout<<*a<<b<<endl;
    cout<<a<<" "<<&b;

    return 0; 
} 

адрес b типизирован и сохранен в a. Насколько мне известно, *a должен указывать на то же место, что и b, и должен даватьто же значение, что и для b. Получение выходных данных a и & b показывает, что оба они указывают на одно и то же место в памяти.Но a * и b дают разные значения в качестве выходных данных. Если бы я не указывал тип указателя, то я бы получил то же значение для * a и b. Может ли кто-нибудь помочь мне найти, что здесь не так? Спасибо заранее

65
0x7fff2e7969fc 0x7fff2e7969fc

1 Ответ

0 голосов
/ 23 февраля 2019

Вы пытаетесь записать переменную (b), которая была объявлена ​​const.Это undefined behavior в C ++.Неопределенное поведение означает, что в этот момент программа может сделать что угодно , все допустимо, включая печать совершенно неправильных чисел или даже сбой.

Сначала вы пообещали, что b является постоянным, и ониВы нарушили это обещание.

Компилятор намекнул, что то, что вы делаете, не разрешено, заставив вас вставить приведение.Без приведения (int*) ваш код не будет компилироваться, потому что он не является правильным.Бросок вокруг const часто является намеком на то, что что-то не так.Существуют допустимые варианты использования const, но не в таких ситуациях, как ваш код, где базовой переменной действительно является const.

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

Наиболее вероятно, что происходит в вашем сценарии:

Компилятор помнит, что вы хотите присвоить значению 5 имя b.Он также понимает, что вы берете указатель на b, поэтому он также резервирует место для b в стеке.Скорее всего, он даже не потрудится поместить 5 в стек до тех пор, пока вы не попытаетесь прочитать его, но вы никогда этого не сделаете.Вместо этого вы перезаписываете местоположение для b в стеке с помощью 6. Таким образом, операторы печати сначала печатают a 6 (для расположения b в стеке), а затем 5 (компилятор просто вставляет 5 везде, где вы используете * 1027).*).

...