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.

  1. ¿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();
    }
    
  2. ¿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

¿Fue útil?

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top