Допустимо ли псевдоним массива char через указатель на int?

Я знаю, что в стандарте явно разрешено следующее:

int n = 0;
char *ptr = (char *) &n;
cout << *ptr;

Как насчет этого?

alignas(int) char storage[sizeof(int)];
int *ptr = (int *) &storage[0];
*ptr = 0;
cout << *ptr;

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

Некоторые части стандарта оставили меня в противоречии; (3.10.10), кажется, указывает на то, что поведение будет неопределенным при условии, что динамический типstorage не являетсяint, Однако определение динамического типа мне неясно, и существованиеstd::aligned_storage приведет меня к мысли, что этоявляется возможный.

 curiousguy13 янв. 2017 г., 18:43
«Динамический тип» полезен для классов, а не для скаляров.
 chbaker010 авг. 2016 г., 02:09
@ user2079303 хороший момент, я добавлю в своем исследовании, что оставило меня в конфликте
 DarthRubik10 авг. 2016 г., 02:08
@ chbaker0 Глядя на ссылку, которую я привел выше, похоже, что пример реализации (надеюсь, соответствует стандарту) делает почти то же самое, что вы делаете здесь
 DarthRubik10 авг. 2016 г., 02:04
Я не знаю, если вы можете сделать это, но это определяется стандартом для доступа к переменной вaligned_storage так, как вы пытаетесь
 chbaker010 авг. 2016 г., 02:15
@DarthRubik Спасибо, я отметил наличие этого в моем редактировании
 eerorika10 авг. 2016 г., 02:07
Я не голосовал, но если бы я попросил ссылки на стандарт, я бы ожидал, что вы покажете свои собственные исследования и процитируете части, которые вы считаете актуальными, и опишите свои собственные выводы, в которых вы не уверены.
 chbaker010 авг. 2016 г., 01:49
Могут ли люди, понижающие голос, оставлять комментарии, пожалуйста?

Ответы на вопрос(3)

Решение Вопроса

Кодint *ptr = (int *) &storage[0]; *ptr = 0; вызывает неопределенное поведение, нарушая правило строгого алиасинга (C ++ 14 [basic.lval] / 10)

Объекты, к которым осуществляется доступ, имеют типchar но у glvalue, используемого для доступа, есть типint.

«Динамический тип объекта» дляchar все ещеchar, (Theдинамический тип отличается только от статического типа в случае производного класса). C ++ также не имеет эквивалента «эффективного типа» C, что позволяет «создавать» типизированные объекты с помощью оператора присваивания в пространстве malloc.

Относительно правильного использованияstd::aligned_storage, вы должны затем использовать размещения новые для создания объекта в хранилище. Использование размещения нового считается закончить срок службыchar (или что угодно) объектов, и создайте новый объект (с продолжительностью динамического хранения) указанного типа, повторно используя то же хранилище. Тогда не будет строгого нарушения псевдонимов.

Вы можете сделать то же самое с массивом char, например:

alignas(int) char storage[sizeof(int)];
int *ptr = new(storage) int;
*ptr = 0;
cout << *ptr;

Обратите внимание, что не вызов псевдо-деструктора илиdelete требуется для встроенного типаint, Это необходимо сделать, если использовать тип класса с нетривиальной инициализацией.Ссылка для дальнейшего чтения

 curiousguy14 янв. 2017 г., 12:08
@ M.M А также каждый объект POD, который помещается в эту область памяти!
 curiousguy09 нояб. 2017 г., 08:00
@ M.M Пожалуйста, объясните, что проблематично с бесконечностью объектов по одному и тому же адресу, если вам не нравится эта идея.
 M.M10 авг. 2016 г., 04:30
В соответствии со стандартом - это правильно, вы должны использовать размещение нового на пространстве malloc перед записью в него.
 M.M10 авг. 2016 г., 04:30
@ chbaker0 да, это не очень хорошо известно; Пропуск нового размещения и выполнение строгих нарушений псевдонимов, по-видимому, работают в большинстве (или во всех случаях), поэтому многие люди просто не знают о проблеме или не имеют отношения к Стандарту.
 M.M14 авг. 2016 г., 06:41
@ T.C. да, надеюсь, все это можно улучшить, чтобы общие конструкции, которые мы обсуждаем, действительно были четко определены
 M.M14 янв. 2017 г., 07:30
@curiousguychar storage[sizeof(int)]; создает массивchar объекты.
 chbaker010 авг. 2016 г., 04:29
Так что это будет означать, что с помощьюmalloc затем используя результирующую память какint или любой другой примитив, кромеchar также не определено, если вы не делаете новое размещение?
 M.M14 янв. 2017 г., 13:41
@curiousguy Стандарт не поддерживает вашу заявку. Действительно, нелепо говорить, что объявление массива char создает фактически бесконечное число объектов. Эта тема о том, что на самом деле говорит стандарт, а не о том, что вы хотите.
 chbaker010 авг. 2016 г., 04:27
Вторая часть дошла до сути моего недоразумения; Я не понимал, что тип объекта был установлен с помощью размещенияnew.
 curiousguy13 янв. 2017 г., 18:44
"Объекты, к которым осуществляется доступ, имеют тип charВы сделали это. Код в порядке.
 T.C.13 авг. 2016 г., 18:02
В части «конец срока службы» - см. P0137R1 для некоторых настроек (и особый случай для массивов беззнаковых символов)

union конструкция может быть полезна здесь.

union похож наstructза исключением того, что все элементыunion заниматьтак же площадь хранения.

Другими словами, они «разные способы увидеть одно и то же», как и ФортранEQUIVALENCE декларация. Так, например:

union {
  int   foo;
  float bar;
  char  bletch[8];
}

предлагает три совершенно разных способа рассмотретьтак же площадь хранения. (Размер хранилищаunion размер его самого длинного компонента.)foo, bar, а такжеbletch все синонимы длятак же место хранения.

union часто используется сtypedef, как показано в этой статье StackOverflow:C: typedef union.

 Jerry Jeremiah10 авг. 2016 г., 03:51
Вопрос имеет тег C ++ и в соответствии сstackoverflow.com/questions/25664848/unions-and-type-punning это недопустимо в C ++ (но это в C).
 Jerry Jeremiah10 авг. 2016 г., 03:59
И этотstackoverflow.com/questions/28521188/... говорит то же самое.
 M.M10 авг. 2016 г., 04:11
C ++ не позволяет вводить типы через объединения. Вы можете только читать из последнего назначенного участника.
 curiousguy14 янв. 2017 г., 14:17
@ М.М "Вы можете только читать из последнего назначенного участника"Это тоже не правда.
 Mike Robinson10 авг. 2016 г., 04:37
Ох, фу ... как ты прав ... мне плохо.: * (  ... ("Тип Пуннинг" ... почему-то я раньше не слышал этот термин. Но мне нравится это.)
*ptr = 0;

пишет в int, так что это доступ к int со значением l типа int, так что часть кода в порядке.

С ролями морально все в порядке, но стандартные тексты C / C ++ не содержат четкого описания приведений, указателей или чего-то фундаментального.

 curiousguy09 нояб. 2017 г., 08:00
@ M.M Подразумевается, что любое использование союза до недавнего времени было неоправданным.
 curiousguy14 янв. 2017 г., 15:46
@ М.М "Они четко описывают это«Я, пожалуйста, чтобы узнать это. Пожалуйста, посмотрите и ответьте на мои многочисленные вопросы относительно указателей:stackoverflow.com/q/32100245/963864
 M.M14 янв. 2017 г., 13:44
Они четко описывают это, вы просто не согласны с последствиями того, что говорится в стандарте, поэтому вы делаете вид, что это не так.

Ваш ответ на вопрос