C++ Почему нельзя хранить адрес переменной в обычной переменой типа int, а нужно писать int*?

135
14 мая 2019, 00:00

Зачем класть адрес переменной, например int, в определенный тип int*, если можно класть адрес в обычную переменную int, предположим, что разрядность процессора точно такая же как и у типа int? В чем проблема?

Answer 1

Во-первых, в терминологии языков C и C++ термин "адрес" является синонимом термина "указатель" (или "значение типа указатель").

Во-вторых, языки С и С++ являются строго типизированными языками. В переменную типа "целое число" нельзя просто так взять и неявно записать значение типа "указатель". Это нарушение правил типизации языков С и С++. (Если вы не понимаете, в чем заключается цель и ценность строгой типизации, то это отдельный широкий вопрос.)

В-третьих, сам ваш вопрос построен на некорректной посылке. Кто вам сказал, что этого делать нельзя? Никто вам не запрещает в С и С++ сохранить значение указателя int * в переменной типа int, если ширина типа int достаточна для этого. Просто для этого требуется явное приведение типа

int a = 0;
int p = (int) &a;

В стандартной библиотеке этих языков есть даже специально заведенные целочисленные типы intptr_t/uintptr_t, которые как раз и предназначены именно для этого, т.е. для хранения приведенных к целому типу значений указателей.

Разумеется, для того, чтобы снова использовать такое сохраненное значение в роли указателя, вам придется сначала явно привести его обратно к типу "указатель".

В далекие 70-е годы, когда язык С еще только зарождался (см. C Reference Manual), он допускал определенные варианты смешанного использования целых типов и указателей. В частности, в левой части оператора -> можно было указывать целочисленные значения

struct S {
  int s_a; /* смещение 0 */
  int s_b; /* смещение 2 */
};
/* "С Reference Manual" явным образом утверждал, 
   что тип `int` имеет размер именно в 2 байта */
...
int a = 0x1234;
a->s_b = 42; /* записываем 42 в int по адресу 0x1236 */
...

Но от таких трюков быстро отказались.

Answer 2

Можно хранить. Просто покажу свой код.

unsigned long long & __getWrapper(){
    static unsigned long long address = 0u; // здесь и хранится адрес
    return address;
}
Wrapper* getWrapper(){
        return (Wrapper*)__getWrapper();
}
void setWrapper( Wrapper * wrapper ){
    __getWrapper() = (unsigned long long)((void*)wrapper);
}
void f(){
     Wrapper * wrapper = getWrapper();
     wrapper->что-то там...
}
int main(){
    Wrapper* wrapper = new Wrapper;
    setWrapper( wrapper );
    f();
    return 0;
}
READ ALSO
В чем преимущество int[] перед vector<int> или array<int>

В чем преимущество int[] перед vector<int> или array<int>

Смотрю разный доступный код по C++ и много где массивы представляют в виде int p[3], напримерСоответственно возник вопрос: это просто привычка...

131
Убрать помехи бинарное изображение C++

Убрать помехи бинарное изображение C++

Превращаю изображение в бинарное(черно-белое):

122
Двухпоточное приложение C++

Двухпоточное приложение C++

Всем привет, есть задача - Основной поток выделяет блок памяти размеров 200кб, заполняет его случайными числами и создает второй поток, который...

140
Поиск линии пикселей одного цвета C++

Поиск линии пикселей одного цвета C++

Есть изображения(ровная прямая линия может быть в любой стороны):

144