Является ли правило псевдонимов симметричным? - PullRequest
1 голос
/ 21 января 2011

У меня был разговор с кем-то по IRC, и этот вопрос возник.Стандарт позволяет нам изменять объект типа int на char lvalue.

int a;
char *b = (char*) &a;
*b = 0;

Разрешено ли нам делать это в противоположном направлении, если мы знаем, что выравнивание в порядке?

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

int a;
a = 0;

Причина состоит в том, что каждый объект содержит последовательность объектов sizeof(obj) unsigned char (называемых "представление объекта ").Если мы изменим int, мы изменим некоторые или все эти объекты.Однако правило псевдонимов гласит, что нам разрешено изменять int на char или unsigned char, но не наоборот.Другой пример

int a[1];
int *ra = a;
*ra = 0;

3.10 / 15 («Совокупный или объединенный тип, который включает в себя ...») описывает только одно направление, но на этот раз нам нужно наоборот («Тип, который являетсятип элемента или нестатического элемента данных агрегата ... ").

Предполагается ли другое направление?Этот вопрос также относится к C.

Ответы [ 3 ]

2 голосов
/ 21 января 2011

Правило псевдонимов просто гласит, что существует один «эффективный тип» (C99 6.5.7, плюс сноска 73) для любого данного объекта в памяти, и любой доступ к такому объекту проходит через одно из:

  • Тип, совместимый с действующим типом (такие квалификаторы, как const и restrict, а также со знаком / без знака могут различаться)
  • Структура или объединение, содержащее один такой тип
  • Тип символа

Эффективный тип, конечно же, не указан в продвинутом - это просто конструкция, используемая для определения псевдонимов.Но цель состоит в том, чтобы просто не получить доступ к одному и тому же объекту с двумя разными не-символьными типами.

Так что ответ, да, вы действительно можете пойти в другом направлении.

1 голос
/ 21 января 2011

Стандарт (C99 6.3.2.3 §7) определяет приведение указателей как «просто отлично», приведенный указатель будет указывать на тот же адрес. (Если процессор не имеет выравнивания, которое делает приведение невозможным, тогда это неопределенное поведение.)

То есть фактический актерский состав сам по себе в порядке. Что произойдет, если вы начнете манипулировать данными ... теперь это другая история, определяемая реализацией.

Вот из стандарта:

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

Когда указатель на объект преобразуется в указатель на тип символа, результат указывает на младший адресуемый байт объекта. Последовательные приращения результата, вплоть до размера объекта, дают указатели в оставшиеся байты объекта. "

"57) В общем, понятие« правильно выровненное »является транзитивным: если указатель на тип A правильно выровнен для указателя на тип B, который в свою очередь правильно выровнен для указателя на тип C, то указатель на тип А правильно выровнен для указателя на тип C. "

0 голосов
/ 22 января 2011

Я думаю, что меня немного смущает вопрос, но 2-й и 3-й примеры обращаются к int через lvalue, который имеет тип объекта (int в примерах).

C ++ 3.10/ 15 в качестве первого пункта утверждает, что все в порядке, чтобы получить доступ к объекту через lvalue, который имеет тип «динамический тип объекта».

Что я неправильно понимаю в вопросе?

...