2015-07-24 2 views
4

Я читаю заметки о reinterpret_cast и правилах его псевдонимов (http://en.cppreference.com/w/cpp/language/reinterpret_cast).Строгое правило сглаживания

Я написал этот код:

struct A 
{ 
    int t; 
}; 

char *buf = new char[sizeof(A)]; 

A *ptr = reinterpret_cast<A*>(buf); 
ptr->t = 1; 

A *ptr2 = reinterpret_cast<A*>(buf); 
cout << ptr2->t; 

Я думаю, что эти правила не применяются здесь:

  • Т2 (возможно, резюме квалифицированных) динамический тип объекта
  • T2 и T1 оба (возможно, многоуровневые, возможно, cv-квалифицированные на каждом уровне) указатели на один и тот же тип T3 (поскольку C++ 11)
  • T2 - это совокупный тип или тип объединения, который содержит один из a (в том числе рекурсивно, элементы субагрегатов и нестатические члены данных объединенных объединений): это позволяет сбрасывать из первого члена структуры и из элемента объединения к структуре/объединению, которая ее содержит.
  • Т2 (возможно, резюме квалифицированных) знаком или без знака вариант динамического типа объекта
  • Т2 (возможно, резюме квалифицированных) базовый класс динамического типа объекта
  • Т2 символ или unsigned char

На мой взгляд, этот код является неправильным. Я прав? Правильно ли код?

С другой стороны, что касается функции соединения (man 2 connect) и struct sockaddr?

int connect(int sockfd, const struct sockaddr *addr, 
       socklen_t addrlen); 

Например. у нас есть struct sockaddr_in, и мы должны передать его в struct sockaddr. Вышеизложенные правила также не применяются, так ли это неверно?

+0

Сделайте это 'char buf [sizeof (A)]' и gcc обнаружит оба нарушения при -Wstrict-aliasing = 2 – Cubbi

+0

Не 'connect' функция C? – Walter

+0

Да, но я сосредотачиваюсь на struct sockaddr не на функции. – Adam

ответ

4

Да, это инвалид, но не потому, что вы преобразования char* в A*: это потому, что вы не получаете в A*, что на самом деле указывает на A* и, как вы определили, ни один из вариантов наложения спектров типа поместиться.

Вы, вероятно, хотите что-то вроде этого:

#include <new> 
#include <iostream> 

struct A 
{ 
    int t; 
}; 

char *buf = new char[sizeof(A)]; 

A* ptr = new (buf) A; 
ptr->t = 1; 

// Also valid, because points to an actual constructed A! 
A *ptr2 = reinterpret_cast<A*>(buf); 
std::cout << ptr2->t; 

Теперь введите сглаживание не войти в него вообще.

Конечно, этот пример надуман, потому что вы только что создали A, но, предположив, что buf на самом деле больше в реальности, и вы создаете распределитель или что-то подобное, это имеет смысл. Просто убедитесь, что вы разместили newA, и вам будет хорошо.

(Как ни странно, при переключении автоматической продолжительности buf хранения, есть еще предупреждение компилятора. Я не могу это объяснить, но это кажется ложной тревоги.)

+0

Meh, переключение на 'char buf [sizeof (A)]' все еще приводит к строгому сглаживанию предупреждения. Может быть, я что-то упустил. Выравнивание? –

+0

«ни один из вариантов сглаживания типа не подходит». - двойной отрицательный, непреднамеренный, я полагаю. – davmac

+2

Были ли какие-то обсуждения по поводу того, является ли предупреждение после размещения-new ложным положительным – Cubbi

Смежные вопросы