(Tutte le citazioni si riferiscono a N1256, che è C99, più rettifiche tecnica (TC3).)
La definizione formale di restrict
è fornita al §6.7.3.1. Cito la sottoclaus più importante qui sotto. P
è un puntatore aggiornato a restrict
per digitare T
il cui ambito è un blocco B
. Un'espressione puntatore E
si dice che sia basata suP
se dipende dal valore di P
stesso, non dal valore a P
.
Durante ogni esecuzione di B
, lasciate L
essere qualsiasi Ivalue che ha &L
basato su P. Se L
è utilizzato per accedere al valore dell'oggetto X
che designa, e X
è anche modificato (con qualsiasi mezzo) , si applicano i seguenti requisiti:
T
non deve essere qualificato.
- Ogni altro valore utilizzato per accedere al valore di
X
deve anche avere l'indirizzo in base a P
.
- Ogni accesso che modifica
X
deve essere considerato anche per modificare P
, ai fini del presente sottopunto.
- Se
P
viene assegnato il valore di un'espressione puntatore E
che si basa su un altro oggetto puntatore limitato P2
, associato blocco B2
, allora o l'esecuzione di B2
inizia prima dell'esecuzione di B
, o l'esecuzione di B2
termina prima del compito.
Se questi requisiti non sono soddisfatti, il comportamento non è definito.
Vediamo quali sono le regole hanno da dire su accessi a parti del array
bar
s' in foo
. Iniziamo con array
, un puntatore qualificato limitato dichiarato nella lista parametri di bar
. Per chiarezza, io alfa-convertire i parametri di foo
:
void foo(float* b, float c, unsigned int n) { /*modify b[i]*/ }
Lo stoccaggio puntato da array
viene modificato anche attraverso b
. Questo è ok con il secondo punto elenco come &array[i*n]
equivale a array+(i*n)
(consultare §6.5.3.2).
Se b
era limitare qualificato, allora dovremmo controllare il quarto punto con P
← b
, B
← foo
, P2
← array
, B2
← bar
. Dal momento che B
è nidificato all'interno di B2
(le funzioni si comportano come se fossero state sottolineate qui, consultare §6.7.3.1.11), viene soddisfatta la prima condizione. C'è anche un'istanziazione del terzo punto (l'accesso a b[i]
in foo
) che non è un problema.
Tuttavia, b
non è qualificato. Secondo §6.3.2.3.2, "Per qualsiasi qualificatore q, un puntatore a un valore non q -qualified può essere convertito in un puntatore allo q - versione qualificata del tipo; i valori memorizzati nei puntatori originali e convertiti devono essere uguali ". Pertanto la conversione da array+(i*n)
a b
è ben definita e ha il significato ovvio, quindi il comportamento del programma è definito. Inoltre, dal momento che b
non è restrict
-qualificato, non è necessario rispettare alcuna condizione di linearità. Ad esempio, il seguente foo
è legale in combinazione con bar
:
void qux(float *v, float *w) {
v[0] += w[0];
}
void foo(float* b, float c, unsigned int n)
{
qux(b,b);
}
AGGIUNTO: Per affrontare la vostra specifica preoccupazione “in bar(), dove si passa l'indirizzo della parte della matrice a foo () ", Questo non è un problema: restrict
si applica al puntatore, non all'array, ed è possibile eseguire aritmetici su di esso (bullet point 2).
Non posso dire se stai dicendo che è giusto o sbagliato, ma puntelli per distribuire completamente lo standard. –
@Matt: il codice è corretto (in parte perché le regole delle restrizioni non stanno facendo molto qui, e in parte perché è possibile convertire il qualificatore restrittivo nel subscope delimitato da 'foo'). – Gilles