2011-01-19 5 views
4

Если у меня есть что-то вроде этого в моем коде:C присвоение структуры одного и того же адреса действительна?

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

Если х и у точки на тот же адрес, что происходит?

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

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

ответ

0

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

На самом деле, это отвеченная частью ответа на Are there any platforms where using structure copy on an fd_set (for select() or pselect()) causes problems?this answer), который я вставить здесь:

Один из следующих проводит:

...

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

...

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

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

1

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

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

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

+0

Нет необходимости делать чек. –

+0

Свергнуть, обет. –

3

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

0

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

+1

Или знаете, что memcpy действителен в этом случае: вероятно, что большинство реализаций memcpy имеют проблему с частичным перекрытием, но не с полным перекрытием; и * x = * y не может привести к частичному перекрытию в соответствующем коде. – AProgrammer