Decrementar un puntero fuera de los límites; incrementándolo en límites [duplicate]

7 minutos de lectura

Decrementar un puntero fuera de los limites incrementandolo en limites
alca

¿Lo siguiente provoca un comportamiento indefinido en la línea 4 y/o 5?

#include <stdio.h>
int main(void)
{
  char s[] = "foo";
  char * p = s - 1;      /* line 4 */
  printf("%s\n", p + 1); /* line 5 */
  return 0;
}

  • Ha pasado un tiempo, pero el duplicado, aunque relacionado, en realidad no parece ser un duplicado de esta pregunta. Podría reabrir, pero como soy la respuesta aceptada, dejaré que otra persona lo haga.

    – Shafik Yaghmour

    1 oct 2014 a las 12:19

  • @ShafikYaghmour: “… el duplicado […] en realidad no parece ser un duplicado …“¿Por qué motivo(s), por favor? Por lo que usted (entre otros) responde, la línea 4 en realidad provoca UB, lo mismo hace el array - 1 en la pregunta vinculada.

    – alk

    1 oct 2014 a las 14:45


  • Aunque los temas son similares, en realidad no son la misma pregunta, me encuentro más escéptico de los cierres duplicados después de esta meta discusión, pero aparentemente hay una gran divergencia de opinión sobre este tema.

    – Shafik Yaghmour

    4 de octubre de 2014 a las 1:52

  • Encontré una situación en la que este comportamiento indefinido en realidad hace que el cálculo sea incorrecto (en un x86 normal): stackoverflow.com/questions/23683029/…

    – Bernd Elkemann

    28 de enero de 2015 a las 20:13

La disminución del puntero fuera de los límites de la matriz no está definida.

estándar C99 el punto 6.5.6 párrafo 8 dice, en parte,

Cuando una expresión que tiene un tipo entero se suma o se resta de un puntero, el resultado tiene el tipo del operando del puntero. … Si tanto el operando puntero como el resultado apuntan a elementos del mismo objeto de matriz, o uno más allá del último elemento del objeto de matriz, la evaluación no producirá un desbordamiento; de lo contrario, el comportamiento no está definido.

Entonces, su línea 4 está invocando un comportamiento indefinido ya que el resultado no está dentro de la matriz ni está más allá del final.

  • La frase “la evaluación no producirá” me da curiosidad si el puntero es realmente evaluado. Y el “p + 1” está seguro dentro de la matriz.

    – Capitán Jirafa

    12 de agosto de 2013 a las 13:31

  • @CaptainGiraffe: el puntero no se evalúa; la expresión es y da como resultado un puntero (de tipo). En este caso tienes expresión s - 1 cuya evaluación en un contexto dado resulta en algún valor. por ejemplo para C[s -> 00000001] los s - 1 evalúa a 00000000. mi lectura es esa evaluación es abstracto aquí y está en el espacio matemático (usted no escribe una expresión que, si se evalúa, daría como resultado …) en lugar de una parte de la ejecución de pasos pequeños.

    – Maciej Piechotka

    12 de agosto de 2013 a las 13:34


  • @MaciejPiechotka Sí, su lectura del texto parece coincidir con las otras respuestas. No estoy muy seguro. Tengo la impresión de que evaluar significa mirar ese lugar; UB por supuesto. Después de todo, debería ser aritmética entera regular, comportándose regularmente (razonamiento anecdótico, lo sé).

    – Capitán Jirafa

    12 de agosto de 2013 a las 13:40

  • @CaptainGiraffe “Tengo la impresión de que la evaluación significa mirar ese lugar”; su impresión es incorrecta; eso es desreferenciar, no evaluación. Maciej también está equivocado: la evaluación no es abstracta, se refiere al cálculo del valor resultante de la aritmética de punteros.

    –Jim Balter

    12 de agosto de 2013 a las 13:43

  • @cmaster No, no es así como funciona. Los compiladores no tienen que buscar un comportamiento indefinido. Nada en el párrafo 8 de 6.5.6 dice que la definición de matriz tiene que ser visible para invocar un comportamiento indefinido.

    –Nigel Harper

    12/08/2013 a las 20:57

1647639916 856 Decrementar un puntero fuera de los limites incrementandolo en limites
yuhao

¡Sí, la línea 4 tiene un comportamiento indefinido!

C99 6.5.6 Operadores aditivos, Sección 8

Cuando una expresión que tiene un tipo entero se suma o se resta de un puntero, el resultado tiene el tipo del operando del puntero. Si el operando puntero apunta a un elemento de un objeto de matriz, y la matriz es lo suficientemente grande, el resultado apunta a un elemento desplazado del elemento original de tal manera que la diferencia de los subíndices de los elementos de la matriz resultante y original es igual a la expresión entera. En otras palabras, si la expresión P apunta a la i-th elemento de un objeto de matriz, las expresiones (P) + N (equivalentemente, N + (P)) y (P) - N(donde N tiene el valor n) apuntan, respectivamente, a la i+n-th y i−n-th elementos del objeto de matriz, siempre que existan. Además, si la expresión P apunta al último elemento de un objeto de matriz, la expresión(P) + 1 apunta uno más allá del último elemento del objeto de matriz, y si la expresión Q apunta uno más allá del último elemento de un objeto de matriz, la expresión (Q) - 1 apunta al último elemento del objeto de matriz. Si tanto el operando puntero como el resultado apuntan a elementos del mismo objeto de matriz, o uno más allá del último elemento del objeto de matriz, la evaluación no producirá un desbordamiento; de lo contrario, el comportamiento no está definido. Si el resultado apunta a uno más allá del último elemento del objeto de matriz, no se utilizará como operando de un elemento unario. * operador que se evalúa.

Decrementar un puntero fuera de los limites incrementandolo en limites
Shafik Yaghmour

¿Lo siguiente provoca un comportamiento indefinido en la línea 4 y/o 5?

Sí, Línea 4 es comportamiento indefinido ya que el puntero no apunta dentro de los límites de la matriz o más allá de los límites de la matriz. Aunque es válido apuntar uno más allá de los límites de la matriz, no puede desreferenciar ese elemento.

La sección correspondiente en el proyecto de norma c99 es 6.5.6 Operadores aditivos párrafo 8:

Cuando una expresión que tiene un tipo entero se suma o se resta de un puntero, el resultado tiene el tipo del operando del puntero. […] Si tanto el operando puntero como el resultado señalar elementos del mismo objeto de matriz, o uno más allá del último elemento del objeto de matrizla evaluación no deberá producir un desbordamiento; de lo contrario, el comportamiento no está definido.

El final del párrafo dice que no deberás deferir uno más allá del último elemento:

[…] Si el resultado apunta a uno más allá del último elemento del objeto de matriz, no se utilizará como operando de un operador unario * que se evalúa

  • Me tomó demasiado tiempo llegar a la especificación, pero sí. Vale la pena señalar que en la práctica esto siempre va a funcionar porque es más difícil hacer que no funcione, pero en teoría no está garantizado.

    – chrylis -cautelosamente optimista-

    12 de agosto de 2013 a las 12:36

  • @chrylis Hay intérpretes de C que detendrán la ejecución en la línea 4.

    –Jim Balter

    12 de agosto de 2013 a las 12:42

  • @JimBalter Ya tuve que pensar en CINT una vez esta semana… sostiene la cabeza

    – chrylis -cautelosamente optimista-

    12 de agosto de 2013 a las 12:44

  • @chrylis: “en la práctica esto siempre va a funcionar” — Esa es una mala suposición. Un compilador optimizador puede suponer que el comportamiento del código está bien definido y transformar el código en función de esa suposición.

    –Keith Thompson

    12 de agosto de 2013 a las 15:04

  • @KeithThompson: como caso especial, si el compilador puede determinar estáticamente que una ruta de código conduce incondicionalmente a un comportamiento indefinido, simplemente puede eliminar esa ruta de código completa de la salida, ya que la única forma en que el programa podría evitar tener un comportamiento indefinido es nunca llegar a esa ruta de código.

    – R.. GitHub DEJA DE AYUDAR A ICE

    13 de agosto de 2013 a las 2:56

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad