На некоторых платформах, учитывая что-то вроде long *x,*y,*z;
, наиболее эффективным способом обработки *x = *y + *z;
может быть:
Добавить младшее слово *y
к младшее слово *z
, отмечая перенос, и сохраните результат в младшем слове *x
.
Добавьте старшее слово *y
к старшее слово *z
вместе с любым переносом из предыдущего шага и сохраните его в старшем слове *x
.
Если младший слово *x
совпало со старшим словом *y
, выполнение операций в этой последовательности приведет к перезаписи старшего слова *y
до того, как оно будет использовано в выражении.
Примечание что с clang и g cc ограничения на перекрытие не ограничиваются примитивными типами. Связанная проблема возникает с конструкцией типа:
struct s { int x[2]; };
int test(struct s *p1, struct s *p2)
{
if (*(p1->x))
*(p2->x+1) = 1;
return *p1->x;
}
Здесь все фактические загрузки и сохранения выполняются путем разыменования указателей типа int*
, а не типа struct s*
, сгенерированного g cc. код требует, чтобы либо p1
, и p2
идентифицировали один и тот же экземпляр struct s
, либо непересекающиеся экземпляры и могут работать некорректно, если они идентифицируют перекрывающиеся экземпляры.