Si entiendo correctamente, este programa tiene un comportamiento indefinido en C++ porque el valor intermedio p + 1 es un puntero a la memoria no inicializada:
int main () { int x = 0; int *p = &x; p = p + 1 - 1; *p = 5; } Si se pusiera void en la lista de argumentos de main (como lo requiere la gramática C), ¿sería también un comportamiento indefinido en C?
Tampoco hay un comportamiento indefinido. Puede considerar un solo objeto como una matriz con un elemento. Usando la aritmética de punteros, el puntero puede apuntar a un elemento más allá del último elemento de la matriz, por lo que esta declaración
p = p + 1 - 1;es correcto.
Del estándar C (6.5.6 Operadores aditivos)
7 Para los propósitos de estos operadores, un apuntador a un objeto que no es un elemento de un arreglo se comporta igual que un apuntador al primer elemento de un arreglo de longitud uno con el tipo del objeto como su tipo de elemento.
y
- ...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.
Presta atención a eso
- ...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.
Creo que es un poco desafortunado que el OP haya elegido p + 1 - 1 como ejemplo porque p + 1 no es un comportamiento indefinido como se muestra en Vlad de la respuesta de Moscú .
La pregunta es más interesante si consideramos p + 2 - 2 . Aquí p + 2 es de hecho un comportamiento indefinido. Pero, ¿importa eso si en la expresión completa "deshacer este cálculo".
Hay un análogo para los números enteros. Por ejemplo, dado i un entero con signo y si i + 2 se desborda, siendo así un comportamiento indefinido, ¿la expresión i + 2 - 2 está bien o es un comportamiento indefinido?
La respuesta a ambos es que es un comportamiento indefinido. Si una expresión es un comportamiento indefinido y el programa alcanzaría esa expresión en su evaluación, entonces todo el programa exhibe un comportamiento indefinido.
Hay un caso más conocido sobre esto: calcular el punto medio de los enteros con signo: (a + b) / 2 es UB si a + b se desborda, incluso si el valor final encaja en el tipo de datos.