С учетом сигнатуры функции, например:
void copySomeInts(int * restrict dest, int * restrict src, int n);
Кто-то, кто хотел, чтобы функция вырабатывала определенное поведение в случае, когда источник и пункт назначения перекрываются [или даже там, где они равны], должен будет приложить дополнительные усилия для этого. Это было бы возможно, например,
void copySomeInts(int * restrict dest, int const * restrict src, int n)
{
for (int i=0; i<n; i++)
{
if (dest+i == src)
{
int delta = src-dest;
for (i=0; i<n; i++)
dest[i] = dest[delta+i];
return;
}
if (src+i == dest)
{
int delta = src-dest;
for (i=n-1; i>=0; i--)
dest[i] = src[delta+i];
return;
}
}
/* No overlap--safe to copy in normal fashion */
for (int i=0; i<n; i++)
dest[i] = src[i];
}
и, таким образом, компилятор, генерирующий код для вызова copySomeInts
, не сможет сделать какие-либо выводы о его поведении, если он не увидит определение copySomeInts
, а не только сигнатуру.
Хотя квалификаторы restrict
не означают, что функция не может обработать случай, когда источник и пункт назначения перекрываются, они бы предположили, что такая обработка, вероятно, будет более сложной, чем это было бы необходимо без квалификатора. Это, в свою очередь, предполагает, что, если только нет явной документации, обещающей обработать этот случай, не следует ожидать, что функция будет обрабатывать ее определенным образом.
Обратите внимание, что в случае, когда источник и место назначения перекрываются, фактически ни одно хранилище не адресуется с использованием указателя src
или чего-либо полученного из него. Если src+i==dest
или dest+i==src
, это будет означать, что src
и dest
идентифицируют элементы одного и того же массива, и, таким образом, src-dest
будет просто представлять разницу в их индексах. Спецификаторы const и restrict для src
означают, что ничто, к которому осуществляется доступ с помощью указателя, полученного из src
, не может быть изменено любым способом во время выполнения функции, но это ограничение применяется только к вещам, доступ к которым осуществляется с помощью указателей, полученных из src
. Если с такими указателями на самом деле ничего не получается, ограничение является пустым.