Безопасно ли приводить int к пустому указателю и снова возвращаться к int? - PullRequest
5 голосов
/ 25 августа 2010

В C и / или C ++: безопасно ли приводить int к пустому указателю и снова возвращаться к int?

На основании вопроса " C ++: безопасно ли приводить указатель на intа позже снова к указателю?".

Ответы [ 8 ]

10 голосов
/ 25 августа 2010

В большинстве современных распространенных машин, вероятно.

Однако я бы поспорил, что есть какой-то неясный компилятор или конфигурация (скажем, 16-битная адресуемая машина, которая использует 32-битную целочисленную арифметику)где это не так.

A uintptr_t гарантированно удерживает оба, так что используйте этот тип, если хотите.

3 голосов
/ 25 августа 2010

Вот пример, где преобразование указателя в целое число может не привести к тому же самому указателю при преобразовании целого числа в указатель.

Учитывая архитектуру, которая имеет 24-битные адреса и использует две 16-битные величины для описания местоположения.Пусть одно количество будет СЕГМЕНТОМ, а другое - СМЕЩЕНИЕМ.Местоположение обозначается обозначением SEGMENT: OFFSET.

Фактический 24-битный (физический) адрес рассчитывается по формуле:

address = segment * 16 + offset.

Используя эту запись, может быть несколько пар SEGMENT: OFFSET, которые описывают один и тот же физический адрес.

При преобразовании в целое число используется 32-разрядная (без знака) величина (для упрощения внутренних вычислений в процессоре).Проблема заключается в том, как преобразовать физический адрес в тот же SEGMENT :: OFFSET, который использовался при создании физического адреса.

Общее уравнение для преобразования целого числа в указатель:

offset = address & 0xFFFF; // Mask off high order bits, keep lower 16.
segment = address >> 16;   // Shift address right 16 bits, zero fill.

Хотя физический адрес этого нового сегмента и смещение равен физическому адресу исходного SEGMENT: OFFSET, сегменты и смещения не обязательно должны быть одинаковыми.

Для оптимизации кода существует процессоринструкции, которые используют относительную адресацию в сегменте.Эти инструкции могут испортиться при изменении значения SEGMENT из-за преобразования с физического адреса.

В этом случае возможно преобразование указателя в целое число.ОДНАКО, преобразование из целого числа в указатель НАСТОЯТЕЛЬНО ОБНАРУЖЕНО.Трудно исправить ошибки могут возникнуть во время выполнения.

Дополнительный вопрос: Можете ли вы назвать реальную архитектуру?

2 голосов
/ 25 августа 2010

Зачем вам это нужно?

Ответ для C, я недостаточно знаю о C ++ для этого: Нет, поведение не определено для приведения int к void*.Прежде всего, вы всегда должны использовать uintptr_t, если у вас есть для такой вещи.Использование int является злоупотреблением.

Тогда C ничего не гарантирует, если ваш uintptr_t не пришел с действительного адреса.Это только гарантирует обратное.Не делайте этого.

Редактировать: Вот соответствующая часть стандарта C99.Как вы можете видеть, все тревоги могут сработать ...

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

Последнее особенно смущает, посколькуэто означает, что значение указателя, полученное таким образом, больше нельзя использовать, пока оно не будет перезаписано:

Определенные представления объекта не должны представлять значение типа объекта.Если сохраненное значение объекта имеет такое представление и читается выражением lvalue, которое не имеет символьного типа, поведение не определено.... Такое представление называется представление ловушки .

1 голос
/ 25 августа 2010

Нет.Могут быть определенные обстоятельства, когда кажется, что он работает для определенного компилятора и настроек, а затем два года спустя вы потратите недели на отладку того, что что-то изменилось, и преобразование больше не работает, как ожидалось.

Если вы просто создаете свой код втаким образом, что такое поведение не требуется (в лучшем случае вообще не используется такое преобразование, в худшем - char[]), и вам не придется беспокоиться о скрытых ошибках в будущем.

1 голос
/ 25 августа 2010

Это реализация, определенная так же, как и последний вопрос, и по той же причине.Это менее вероятно приведет к неправильному поведению, но все равно будет определено реализацией.

1 голос
/ 25 августа 2010

Нет.Пустой указатель ничем не отличается от любого другого указателя по размеру.Следовательно, он будет сталкиваться с теми же типами проблем, что и другие типы указателей.

0 голосов
/ 26 августа 2010

Если диапазон ваших целых чисел довольно мал, вы всегда можете сделать что-то вроде:

static const char dummy[MAXVAL];

, а затем используйте dummy+i в качестве способа кодирования i в качестве указателя. Это на 100% портативно. Если вы заботитесь только о том, чтобы он был переносимым на 99%, вы можете использовать (char *)0 + i.

0 голосов
/ 25 августа 2010

Не обязательно.Зависит от размера указателя.Почему вы хотите это сделать?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...