preguntas puntero restringidas
-
25-09-2019 - |
Pregunta
Estoy un poco confundido acerca de las reglas con respecto a los punteros restringidas. Tal vez alguien por ahí me puede ayudar a cabo.
-
¿Es legal para definir punteros restringidas anidados de la siguiente manera:
int* restrict a; int* restrict b; a = malloc(sizeof(int)); // b = a; <-- assignment here is illegal, needs to happen in child block // *b = rand(); while(1) { b = a; // Is this legal? Assuming 'b' is not modified outside the while() block *b = rand(); }
-
¿Es legal para derivar un valor de puntero restringida de la siguiente manera:
int* restrict c; int* restrict d; c = malloc(sizeof(int*)*101); d = c; for(int i = 0; i < 100; i++) { *d = i; d++; } c = d; // c is now set to the 101 element, is this legal assuming d isn't accessed? *c = rand();
Gracias! Andrew
Solución
Como referencia, aquí está la restrict
calificador es bastante enrevesado definición (de C99 6.7.3.1 "definición formal de restringir"):
Sea D una declaración de un ordinario identificador que proporciona un medio de la designación de un objeto P como una restringir cualificado puntero de tipo T.
Si aparece D dentro de un bloque y no tiene la clase de almacenamiento o externa, se dejó B el bloque. Si D aparece en la lista de parámetros declaraciones de una función definición, deje B el bloque asociado. De lo contrario, al B denotar el bloque de principal (o el bloque cualquiera que sea su función se llama a el arranque del programa en una independiente medio ambiente).
En lo que sigue, un puntero la expresión de E se dice que está basado en objeto P si (en algún momento secuencia en la ejecución de B antes de la evaluación de E) la modificación de P a punto a una copia del objeto de matriz en señaló anteriormente que se iba a cambiar el valor de E. Nota que "basa" es definido sólo por las expresiones con tipos de puntero.
Durante cada ejecución de B, sea L cualquier valor-I que tiene & L basado en P. Si L se utiliza para acceder al valor de la objeto X que designa, y X es también modificado (por cualquier medio), entonces la siguientes requisitos se aplican: T deberá no sea const-calificado. Uno sí y otro no lValue utilizada para acceder al valor de X tendrá además su dirección sobre la base de P. Cada acceso que modifica X, deberán ser considerado también para modificar P, para A efectos de este apartado. Si p se le asigna el valor de un puntero la expresión de E que se basa en otra restringido objeto puntero P2, asociado con el bloque B2, entonces o bien la ejecución de B2 deberá comenzar antes la ejecución de B, o de la ejecución de B2 terminará antes de la asignación. Si estos requisitos no se cumplen, entonces el comportamiento no está definido.
A continuación, una ejecución de medios que B porción de la ejecución de la programa que correspondería a la tiempo de vida de un objeto con tipo escalar y la duración del almacenamiento automático asociado con B.
Mi lectura de los medios anteriores que, en su primera pregunta, a
no se puede asignar a b
, incluso dentro de un bloque de "niño" - el resultado es indefinido. Tal asignación se podría hacer si b
fueron declarados en que 'sub-bloque', pero desde b
se declara en el mismo alcance que a
, la asignación no se puede hacer.
Para la pregunta 2, las asignaciones entre c
y d
también resulta en un comportamiento indefinido (en ambos casos).
El bit correspondiente de la norma (por ambas preguntas) es:
Si P se le asigna el valor de una puntero de la expresión de E que se basa en otro P2 objeto de puntero restringido, asociado con el bloque B2, entonces o bien la ejecución de B2 deberá comenzar antes la ejecución de B, o de la ejecución de B2 terminará antes de la asignación.
Desde los punteros restringidas están asociados con el mismo bloque, no es posible para el bloque B2 para comenzar antes de la ejecución de B, o para B2 para terminar antes de la asignación (desde B y B2 son el mismo bloque).
La norma da un ejemplo que hace que esta bastante claro (creo - la claridad de 4 párrafos cortos de la definición restrict
está a la par con C ++ 's reglas de resolución de nombres):
Ejemplo 4:
La norma que limita las asignaciones entre punteros restringidas no lo hace distinguir entre una llamada de función y un bloque anidado equivalente. Con una excepción, sólo se asignaciones "-exterior para-interiores" entre punteros restringidas declaran en anidada bloques han definido comportamiento.
{ int * restrict p1; int * restrict q1; p1 = q1; // undefined behavior { int * restrict p2 = p1; // valid int * restrict q2 = q1; // valid p1 = q2; // undefined behavior p2 = q2; // undefined behavior } }
Otros consejos
El tipo restrict
calificador es un indicación para el compilador de que, si la memoria dirigida por el puntero restrict
cualificado se modifica, ningún otro puntero acceder a esa misma memoria. El compilador puede optar por código de optimizar la participación de los punteros restrict
calificado de una manera que de otra manera podría resultar en un comportamiento incorrecto. Es responsabilidad del programador para asegurar que restringen calificados punteros se utilizan ya que estaban destinados a ser utilizados. De lo contrario, un comportamiento indefinido puede resultar. ( enlace )
Como se puede ver a partir de la descripción anterior, tanto en sus asignaciones son ilegales, que puede trabajar en ejecutables producidos por algunos compiladores, pero romper en otras. No espere que el propio compilador para emitir errores o advertencias como restrict
solo da una oportunidad para llevar a cabo cierta optimización, que puede optar por no llevar a cabo, al igual que en el caso de volatile
.