, Я ничего не знаю в Стандарте, который бы рассматривал сравнение значения указателя со значением другого указателя как любой вид доступа к цели указателя, за исключением узкого случая, когда указатель нацелен на самого себя.
оложим, у нас есть объявление функции, для которого у нас нет доступа к ее определению:
void f(int * restrict p, int * restrict q, int * restrict r);
Поскольку мы не знаем, как получить доступ к указателям, мы не можем знать, вызовет ли вызов неопределенное поведение или нет - даже если мы передаем тот же указатель, как объясняется в примере в 6.7.3.1.10:
Объявления параметров функции:
void h(int n, int * restrict p, int * restrict q, int * restrict r)
{
int i;
for (i = 0; i < n; i++)
p[i] = q[i] + r[i];
}
проиллюстрировать, как неизмененный объект может быть наложен через два ограниченных указателя. В частности, еслиa
а такжеb
являются непересекающимися массивами, вызовом формыh(100, a, b, b)
определил поведение, потому что массивb
не изменяется внутри функцииh
.
Следовательно,restrict
Излишним в этих случаях, кроме как подсказка / аннотация для вызывающих, разве мы не знаем что-то больше о функции?
Например, давайте возьмемsprintf
(7.21.6.6) из стандартной библиотеки:
конспект
#include <stdio.h>
int sprintf(char * restrict s,
const char * restrict format, ...);
Описание
sprintf
функция эквивалентнаfprintf
за исключением того, что вывод записывается в массив (определяется аргументомs
), а не в поток. (...)
Из резюме и первого предложения описания мы знаем, чтоs
будет написано иs
является ограниченным указателем. Следовательно, можем ли мы уже предполагать (не читая дальше), что вызов подобен:
char s[4];
sprintf(s, "%s", s);
вызовет неопределенное поведение?
Если да, то: последнее предложениеsprintf
лишнее описание (даже если уточняющее)?
Если копирование происходит между объектами, которые перекрываются, поведение не определено.
Если нет, то наоборот:restrict
квалификатор лишний, поскольку описание - это то, что фактически дает нам знать, что будет неопределенным поведением?