Cuando se utiliza un puntero restringen en C, ¿está bien para cambiar una variable utilizando su identificador inicial?

StackOverflow https://stackoverflow.com/questions/3936060

  •  30-09-2019
  •  | 
  •  

Pregunta

Cuando se utiliza un puntero restrict en C, ¿está bien para cambiar la variable utilizando su inicial Identificador ? Por ejemplo:

int foo = 0;

int * restrict fooPtr = &foo;
++(*fooPtr);                   // Part 1: foo is 1 (OK)

++foo;                         // Part 2: foo is 2 (Is this OK?)

int * fooPtr2 = &foo;
++(*fooPtr2);                  // Part 3: foo is 3 (BAD: You shouldn't access via a second pointer)

... me cambió el valor de foo a foo después de la restrict fooPtr se ha creado.

Parte 1 se ve bien para mí. Estoy confundido acerca de Parte 2 . Y por lo que sé sobre restrict, Parte 3 es malo (compilador lo permite, pero su comportamiento no está definido, y es responsabilidad del programador que no lo haga).

¿Fue útil?

Solución

No, la parte 2 no está bien.

La parte específica de la norma es 6.7.3.1/4. Esta sección es bastante denso, y toma unos pocos relee, pero P es un restringen puntero, y X es un objeto que se utiliza para el acceso, y el que se modifica. Así que en su ejemplo P es fooPtr y X es foo. A continuación:

  

Cada dos lvalue utiliza para acceder a la   valor de X también tendrá su domicilio   basado en P.

"basado en" se define en el párrafo anterior, y para resumir, la foo lvalue hace no tiene su dirección en base al restringir el puntero P. Así que la regla se rompe cuando se accede al objeto foo a través de su propio nombre.

Parte 3 no está bien por exactamente la misma razón, el *fooPtr2 lvalue no se basa en P tampoco, pero también se utiliza para el acceso X.

Yo digo "no está bien" - para ser más precisos, la combinación de 1 + 2 provoca un comportamiento indefinido, al igual que la combinación de 1 + 3. Mientras que en realidad no acceso al objeto a través del puntero restringir, ninguno de la definición de "restringir entra en acción". Si quería que podría eliminar la parte 1, retener el puntero restringir sin uso, y luego 2 y 3 estaría bien.

Otros consejos

Sí, "parte 3" es un comportamiento indefinido. A partir de la especificación C99 (6.7.3, párrafo 7):

  

Un objeto que se accede a través de una   restringir-cuali puntero fi ed tiene una   asociación especial con ese puntero.   Esta asociación, definido en 6.7.3.1   a continuación, requiere que todos los accesos a   que el uso objeto, directa o   indirectamente, el valor de esa   puntero en particular.

Yo diría # 2 es mala. Por ejemplo, el compilador puede optimizar mediante la carga del valor en * fooPtr en un registro, y luego escribir que volver valor del registro a foo de nuevo más tarde - después de su ++ foo, por lo que el foo ++ se pierde.

Si se asume que todas las partes de su pregunta se producen en el mismo bloque, no está bien para acceder al valor de foo directamente (parte 2), ni para acceder a ella a través de otro puntero (parte 3):

  • 6.7.3.1 Definición formal de restringir
  

Cada dos lvalue utiliza para acceder al valor de X también tendrá su dirección basada en P.

La definición formal de restrict es bastante difícil de seguir (al menos lo es para mí), sin embargo la siguiente descripción menos formal también de las sumas estándar es bastante bien (al menos para este caso):

  

Un objeto que se accede a través de un puntero restringir-calificado tiene una asociación especial   con ese puntero. Esta asociación, definido en 6.7.3.1 más adelante, requiere que todos los accesos a que el uso objeto, directa o indirectamente, el valor de ese puntero particular.

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