Что такое тип данных uintptr_t - PullRequest
       41

Что такое тип данных uintptr_t

219 голосов
/ 04 декабря 2009

Что такое uintptr_t и для чего его можно использовать?

Ответы [ 4 ]

219 голосов
/ 04 декабря 2009

Во-первых, во время, когда был задан вопрос, uintptr_t не было в C ++. Это в C99, в <stdint.h>, как необязательный тип. Многие компиляторы C ++ 03 предоставляют этот файл. Это также в C ++ 11, в <cstdint>, где опять-таки это необязательно, и который ссылается на C99 для определения.

В C99 это определяется как «целочисленный тип без знака со свойством, что любой действительный указатель на void может быть преобразован в этот тип, затем преобразован обратно в указатель на void, и результат будет сравниваться с исходным указателем» .

Примите это, чтобы означать, что это говорит. Это ничего не говорит о размере.

uintptr_t может быть того же размера, что и void*. Это может быть больше. Вероятно, он может быть меньше, хотя такая реализация на C ++ подходит извращенно. Например, на некоторой гипотетической платформе, где void* составляет 32 бита, но используется только 24 бита виртуального адресного пространства, вы можете иметь 24-битный uintptr_t, который удовлетворяет требованию. Я не знаю, почему реализация сделала бы это, но стандарт разрешает это.

171 голосов
/ 04 декабря 2009

uintptr_t - это целочисленный тип без знака, который может хранить указатель. Что обычно означает, что это тот же размер, что и указатель.

Опционально определяется в C ++ 11 и более поздних стандартах.

Распространенная причина, по которой необходимо иметь целочисленный тип, который может содержать тип указателя архитектуры, - выполнять целочисленные операции над указателем или скрывать тип указателя, предоставляя его как целочисленный «дескриптор».

Редактировать: Обратите внимание, что у Стива Джессопа есть несколько очень интересных дополнительных деталей (которые я не буду красть) в другом ответе здесь для вас педантичных типов:)

18 голосов
/ 04 декабря 2009

Это целое число без знака, точно равное размеру указателя. Всякий раз, когда вам нужно сделать что-то необычное с указателем - например, инвертировать все биты (не спрашивайте, почему), вы приводите его к uintptr_t и манипулируете им как обычному целому числу, а затем возвращаете обратно.

8 голосов
/ 25 декабря 2015

Уже есть много хороших ответов на часть «что такое тип данных uintptr_t». Я попытаюсь ответить на вопрос "для чего он может быть использован?" часть в этом посте.

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

Таким образом, чтобы выполнять побитовые операции с указателями, нужно привести указатели к типу unitpr_t, а затем выполнить побитовые операции.

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

 template <typename T>
 T* xor_ptrs(T* t1, T* t2)
 {
     return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(t1)^reinterpret_cast<uintptr_t>(t2));
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...