Путаница в неопределенном поведении ограничивающего квалификатора
Я видел следующий пример на cppreference.
void f(int n, int * restrict p, int * restrict q)
{
while(n-- > 0)
*p++ = *q++; // none of the objects modified through *p is the same
// as any of the objects read through *q
// compiler free to optimize, vectorize, page map, etc.
}
void g(void)
{
extern int d[100];
f(50, d + 50, d); // OK
f(50, d + 1, d); // Undefined behavior: d[1] is accessed through both p and q in f
}
В этом примере вызов f(50, d + 50, d);
хорошо
Но я не понимаю, звоню f(50, d + 1, d)
; является неопределенным поведением. Зачем?
1 ответ
restrict
Спецификатор указателя означает, что любой объект, доступ к которому осуществляется через этот измененный указатель, не будет доступен через другие указатели в течение времени существования этого указателя. Другими словами, когда к объекту обращаются через указатель p
и изменены во время p
Это означает, что доступ к нему возможен только через p
в этом объеме. Нарушение этого ограничения приводит к неопределенному поведению.
В f(50, d + 50, d);
, p
будет использоваться для изменения d[50]
вплоть до d[99]
, а также q
будет использоваться для доступа d[0]
вплоть до d[49]
, Там нет перекрытия, так что все в порядке.
В f(50, d + 1, d);
, p
будет использоваться для изменения d[1]
вплоть до d[50]
, а также q
будет использоваться для доступа d[0]
вплоть до d[49]
, Поскольку некоторые элементы (например, d[1]
) изменены через p
и прочитать q
это нарушение restrict
Классификатор.