недопонимание при присваивании указателей

Всем привет! Продолжаю свое изучение языка Си маленькими шажками, и вот начал такую тему как "указатели". Сначала было понятно, по ресурсам в интернете дошел до раздела по изменению типа указателя, и вот тут начались появляться вопросы.. Томить не буду, но присваивание ниже я совсем не понимаю: почему у первого указателя такое большое значение, а не 10? почему второй и четвертый указатели показывают, по сути, правильное значение, в отличие от остальных? неужели все настолько сильно зависит от типа данных?

#include <iostream>#include<stdlib.h>
#include<stdio.h>
#include<math.h>

int main()
{
        int a = 1;
        float b = 2;
        double c = 3;
        int* p1 = &a;
        float* p2 = &b;
        double* p3 = &c;
        void* p4 = NULL;

    printf("a=%d\tb=%f\tc=%lf\n", a, b, c);
    *p1 = 5;
    *p2 = *p2 * *p1;
    *p3 = sqrt(*p3);
    printf("a=%d\tb=%f\tc=%lf\n", a, b, c);
    printf("*p1=%d\t*p2=%f\t*p3=%lf\n\n", *p1, *p2, *p3);
    p1 = (int*)p2;
    p3 = (double*)p2;
    p4 = p2;
    printf("p1=%p\tp2=%p\tp3=%p\tp4=%p\n", p1, p2, p3, p4);
    printf("*p1=%d\t*p2=%f\t*p3=%f\t*(float*)p4=%f\n\n", *p1, *p2, *p3, *(float*)p4);

}

Ответы (1 шт):

Автор решения: LShadow77

С точки зрения процессора, указатель - это всего лишь адрес в памяти первого байта данных, на которые собственно ссылается этот указатель. А тип указателя говорит компилятору о том, как именно эти данные интерпретировать. Так, объявление int* p1 говорит компилятору о том, что данные, на которые ссылается указатель p1, являются числом типа int. А объявление float* p2 означает, что данные по указателю p2 - это число типа float. А теперь посмотрите внимательно на ваше присваивание:

p1 = (int*)p2;

После выполнения этой строки кода, указатели p1 и p2 будут содержать одинаковый адрес, а значит будут ссылаться на один и тот же блок данных. Только при обращении к этому блоку через p2, он будет интерпретироваться как float, а через p1 - как int. Через p2 вы получили по этому адресу число 10.0 в формате, соответствующему типу float. Если представить это число в виде шестнадцатиричной последовательности байт, то оно будет выглядеть так: 41 20 00 00. А если трактовать эти данные не как float, а как int, то это и будет как раз то большое число 1092616192, что вывелось на экран при обращении к нему через указатель p1.

Подведу итог: при обращении к некоторому блоку данных типа A через указатель, ссылающийся на тип данных B, приведения типа A к типу B, т.е. преобразования их из одного формата в другой не происходит! Просто данные типа A трактуются так, как будто они имеют тип B. Нужно быть очень осторожным с подобным "жонглированием" указателями, т.к. это легко может привести к ошибкам времени выполнения программы!

→ Ссылка