Можно ли выполнить арифметическую операцию над пустым указателем с sizeof? - PullRequest
1 голос
/ 22 декабря 2010

Можно ли выполнить арифметическую операцию над пустым указателем без использования приведения?

Если у меня есть универсальная функция, которая принимает указатель неизвестного типа и целое число, определяющее размер типа. Можно ли выполнить некоторую арифметику указателей только с двумя аргументами?

void* Function( void* ptr, int size);

Ответы [ 2 ]

4 голосов
/ 22 декабря 2010

Нет, потому что компилятор не знает размер элемента (ов), на который указывает указатель void.Вы можете привести указатель к (char *), чтобы сделать то, что вы хотите выше.

1 голос
/ 22 декабря 2010
  • Предупреждение - приведенное ниже, вероятно, вводит в заблуждение. Как указано другими в комментариях (особая благодарность Стиву Джессопу), приведенный ниже объединенный тип каламбура не имеет особых гарантий в стандартном C ++ по сравнению с каламбурами на основе приведения, и использование приведений к char* для выполнения арифметики с указателями, вероятно, будет более переносимый, который использует союзы для преобразования в целые числа.

Для этого вам нужна некоторая форма штамповки типов из-за массивоподобной семантики указателей в стандарте C ++. Я буду обманывать, используя каламбур на основе профсоюзов ...

inline void* Ptr_Add  (void* p1, std::ptrdiff_t p2)
{
  union
  {
    void*          m_Void_Ptr;
    std::ptrdiff_t m_Int;
  } l_Pun;

  l_Pun.m_Void_Ptr =  p1;
  l_Pun.m_Int      += p2;

  return l_Pun.m_Void_Ptr;
}

У меня есть этот точный код в моей библиотеке, наряду с некоторыми другими для выполнения арифметических и побитовых операций с байтовыми указателями. Существуют каламбуры на основе объединения, потому что каламбуры на основе приведения могут быть хрупкими (анализ псевдонима указателя в оптимизаторе может не определить псевдоним, поэтому полученный код ведет себя неправильно).

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

Как подсказывает ruslik, в GCC есть расширение, которое (если вы не возражаете против непереносимого кода) рассматривает размер void как 1, так что вы можете использовать + на void* для добавить смещение в байтах.

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