Страницы

Поиск по вопросам

четверг, 5 декабря 2019 г.

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

#cpp #c #указатели #адрес


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


Ответы

Ответ 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 */ ... Но от таких трюков быстро отказались.

Ответ 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; }

Комментариев нет:

Отправить комментарий