C структура присвоения того же адреса действительны? - PullRequest
4 голосов
/ 19 января 2011

Если у меня есть что-то подобное в моем коде:

void f(struct foo *x, struct foo *y)
{
  *x = *y; // structure copy (memcpy?)
}

Если x и y указывают на один и тот же адрес , что происходит?

Это допустимокод, а что если компилятор преобразует присваивание в вызов memcpy с потенциально недопустимыми операндами (им нельзя перекрывать друг друга)?

[Да, я знаю, что в этом случае я могу использовать «restrict»,но фактический код, который мы нашли, заставил нас подумать, что он автоматически генерируется бизоном, поэтому мы задались вопросом, должен ли он всегда быть действительным, и должен ли компилятор использовать memmove или что-то еще, что допускает перекрытие ..]

Ответы [ 4 ]

3 голосов
/ 19 января 2011

Структура назначения совершенно законна. Поэтому компилятор будет генерировать правильный код (несмотря на ошибки компилятора).

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

Это выглядит совершенно актуально для меня. Да, это приведет к некоторому виду memcpy.

Два указателя на struct, подобные этому, должны быть либо одинаковыми, либо не перекрываться вообще. Таким образом, вы могли бы проверить, равны ли указатели, раньше.

(Вы, конечно, можете обмануть свой код, чтобы иметь реальное совпадение, но для этого должна быть действительно особая причина.)

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

[Да, отвечая на мой собственный вопрос, как я это увидел, немного посмотрев в стандарт и усердно ища соответствующие вопросы здесь]

На самом деле, на это отвечает часть ответа на Существуют ли какие-либо платформы, где использование структурного копирования в fd_set (для select () или pselect ()) вызывает проблемы? this ответ ), который я здесь вставлю:

Должно быть выполнено одно из следующих действий:

...

левый операнд имеет квалифицированную или неквалифицированную версию структуры или типа объединения, совместимого с типом правого;

...

Если значение, хранимое в объекте, считывается из другого объекта, который каким-либо образом перекрывает хранилище первого объекта, то перекрытие должно быть точным, и два объекта должны иметь квалифицированные или неквалифицированные версии совместимого типа; в противном случае поведение не определено.

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

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

Это действительный код. Компилятор не может предположить x! = Y, поэтому он должен использовать безопасное memmove.

...