7

Некоторые авторы используют двойное преобразование через void* с помощью static_cast, вида:

long* px;
char* p = static_cast<char*>(static_cast<void*>(px));

вместо reinterpret_cast:

long* px;
char* p = reinterpret_cast<char*>(px);

В чем преимущество/недостатки первого варианта?

αλεχολυτ
  • 28,987
  • 13
  • 60
  • 119
  • 1
    Сейчас явно будет комментарий о strict aliasing :) – Harry Dec 27 '17 at 15:04
  • Даже если переводят его, а не в него? Вроде тут написано наоборот? Или я опять не так понял? – Harry Dec 27 '17 at 15:10
  • второй вариант более безопасен – AR Hovsepyan Dec 27 '17 at 15:12
  • @ARHovsepyan кмк, второй опаснее, т.к. в первый кроме указателя ничего не подставишь по ошибке. – Vladimir Gamalyan Dec 27 '17 at 15:12
  • Да какой компилятор не возьми - код-то один и тот же... https://godbolt.org/g/NBBj3S – Harry Dec 27 '17 at 15:14
  • Vladimir, в С++ я не профессионал, но насколько я понимаю статически размещать тип по некому конкретному адресу менее безопасен... – AR Hovsepyan Dec 27 '17 at 15:40
  • 4
    Приведение одного указательного типа на объект к другому указательному типу на объект посредством reinterpret_cast по-определению осуществляется через двойной static_cast. Пруф – wololo Dec 27 '17 at 15:42
  • Например С++ core guidelines рекомендуют не использовать reinterpter_cast. Собственно там рекомендуют по возможности отказываться от кастования, но reinterpter_cast идет первым пунктом. – user7860670 Dec 27 '17 at 18:32
  • @VTT Верно. Но про static_cast для указателей (кроме downcast) там же нет вроде рекомендаций? – Vladimir Gamalyan Dec 27 '17 at 18:37

2 Answers2

5

Двойное преобразование static_cast с преобразованием в void* на первом шаге ограничивает возможный тип аргумента указателем, и не позволяет использовать в качестве него целый тип. Пример:

int  i = 42;
int* p = nullptr;

// Различное поведение при использовании целого аргумента    
static_cast<short*>(static_cast<void*>(i)); // ошибка компиляции
reinterpret_cast<short*>(i);                // ok

// Эквивалентны при использовании аргумента указателя
static_cast<short*>(static_cast<void*>(p)); // ok
reinterpret_cast<short*>(p);                // ok
αλεχολυτ
  • 28,987
  • 13
  • 60
  • 119
1

Вообще-то один static_cast даже лишний, можно определить шаблонную функцию специально для указателей, нельзя записать в строчку, как вариант с двумя static_cast, зато понятно, что имеется в виду.

template <typename U,typename T>
inline U* pointer_cast(T* p) 
{ 
    void* t = p; 
    return static_cast<U*>(t); 
}
Alex Titov
  • 1,261