pic16f84 modos microcontrolador instrucciones indirecto ensamblador ejemplos directo direccionamiento c++ pointers language-lawyer indirection lvalue-to-rvalue

c++ - modos - ¿Exige el estándar una conversión de lvalue a rvalue de la variable de puntero cuando se aplica el direccionamiento indirecto?



modos de direccionamiento ensamblador ejemplos (2)

Creo que te estás acercando a esto desde un ángulo bastante oblicuo, por así decirlo. Según §5.3.1 / 1:

El operador unario * realiza una indirección : la expresión a la que se aplica debe ser un puntero a un tipo de objeto o un puntero a un tipo de función y el resultado es un lvalor que se refiere al objeto o función al que apunta la expresión. Si el tipo de expresión es "puntero a T", el tipo del resultado es "T".

Aunque esto no habla de la conversión de valor a valor, requiere que la expresión sea un puntero a un objeto o función. Un puntero no inicializado no será (excepto, tal vez por accidente) algo así, por lo que el intento de anular la referencia da un comportamiento indefinido.

TL; DR

Dado el siguiente código:

int* ptr; *ptr = 0;

¿ *ptr requiere una conversión de ptr de ptr antes de aplicar el ptr indirecto?

La norma cubre el tema del valor de valor a valor en muchos lugares, pero no parece especificar suficiente información para determinar si el operador * requiere tal conversión.

Detalles

La conversión de lvalue a rvalue se trata en N3485 en la sección 4.1 párrafo 1 de conversión de lvalue a rvalue y dice (el énfasis es más adelante ):

Un glvalue (3.10) de un tipo T sin función no matricial se puede convertir en un valor predefinido.53 Si T es un tipo incompleto, un programa que necesita esta conversión está mal formado. Si el objeto al que se refiere el glvalue no es un objeto de tipo T y no es un objeto de un tipo derivado de T, o si el objeto no está inicializado, un programa que necesita esta conversión tiene un comportamiento indefinido . [...]

También lo hace *ptr = 0; ¿Necesitas esta conversión ?

Si vamos a la sección 4 párrafo 1 dice:

[...] Se aplicará una secuencia de conversión estándar a una expresión si es necesario para convertirla en un tipo de destino requerido.

Entonces, ¿cuándo es necesario ? Si nos fijamos en la sección 5 Expresiones, la conversión de valor-a-valor se menciona en el párrafo 9 que dice:

Cada vez que aparece una expresión de glvalue como un operando de un operador que espera un prvalue para ese operando, las conversiones estándar de lvalue-to-rvalue (4.1), array-to-pointer (4.2) o function-to-pointer (4.3) son Aplicado para convertir la expresión a un prvalue. [...]

y el párrafo 11 que dice:

En algunos contextos, una expresión solo aparece por sus efectos secundarios. Dicha expresión se denomina expresión de valor descartado. [...] La conversión de lvalue a rvalue (4.1) se aplica si y solo si la expresión es un lvalue de tipo calificado volátil y es uno de los siguientes [ ...]

ninguno de los párrafos parece aplicarse a este ejemplo de código y 5.3.1 Operadores unarios, el párrafo 1 dice:

El operador unario * realiza una indirección: la expresión a la que se aplica debe ser un puntero a un tipo de objeto o un puntero a un tipo de función y el resultado es un lvalor que se refiere al objeto o función al que apunta la expresión. Si el tipo de la expresión es "puntero a T", el tipo del resultado es "T". [Nota: la dirección indirecta a través de un puntero a un tipo incompleto (que no sea cv void) es válida. El valor l así obtenido se puede utilizar de manera limitada (para inicializar una referencia, por ejemplo); este lvalue no se debe convertir en un prvalue, ver 4.1. "Nota final"

Parece que no requiere el valor del puntero y no veo ningún requisito para la conversión del puntero. ¿Me falta algo?

¿Por qué nos importa?

He visto una respuesta y comentarios en otras preguntas que afirman que el uso de un puntero no inicializado es un comportamiento indefinido debido a la necesidad de una conversión de ptr de ptr antes de aplicar el ptr indirecto. Por ejemplo: ¿Dónde exactamente el estándar de C ++ dice que la desreferenciación de un puntero sin inicializar es un comportamiento indefinido? hace este argumento y no puedo conciliar el argumento con lo que se presenta en ninguna de las versiones preliminares recientes de la norma. Como lo he visto varias veces, he querido obtener una aclaración.

La prueba real de un comportamiento indefinido no es tan importante ya que, como señalé en la pregunta anterior, tenemos otras formas de llegar a un comportamiento indefinido.


He convertido la sección de actualización en mi pregunta en una respuesta, ya que en este punto parece ser la respuesta, aunque insatisfactoria, mi pregunta no tiene respuesta:

dyp me señaló dos hilos relevantes que cubren un terreno muy similar:

El consenso parece ser que la norma no está bien especificada y, por lo tanto, no puedo proporcionar la respuesta que estoy buscando, Joseph Mansfield publicó un informe de defectos en esta falta de especificación , y parece que todavía está open y no está claro cuándo puede ser aclarado

Hay algunos argumentos de sentido común que se deben hacer en cuanto a la intención de la norma. Uno puede argumentar Logicialmente, un operando es un valor si la operación requiere usar el valor de ese operando . Otro argumento es que si volvemos a mirar el borrador del estándar C99, se dice que la conversión de un valor a otro se realiza de forma predeterminada y se observan las excepciones. La sección relevante del borrador de la norma C99 es 6.3.2.1 Valores, arreglos y designadores de funciones, párrafo 2, que dice:

Excepto cuando es el operando del operador sizeof, el operador unario, el operador ++, el operador - o el operando izquierdo de. operador o un operador de asignación, un lvalue que no tiene un tipo de matriz se convierte al valor almacenado en el objeto designado (y ya no es un lvalue). […]

lo que básicamente dice, con algunas excepciones, que un operando se convierte al valor almacenado y, como el direccionamiento indirecto no es una excepción, si se aclara que también es el caso en C ++ , la respuesta a mi pregunta es .

Como intenté aclarar, la prueba de un comportamiento indefinido fue menos importante que aclarar si una conversión de valor a valor es obligatoria. Si queremos probar un comportamiento indefinido tenemos enfoques alternativos. El enfoque de Jerry es de sentido común y en ese sentido, la indirección requiere que la expresión sea un puntero a un objeto o función y que un valor indeterminado solo apunte por accidente a un objeto válido. En general, el borrador del estándar C ++ no proporciona una declaración explícita para decir que el uso de un valor indeterminado no está definido, a diferencia del borrador del estándar C99 En C ++ 11 y la norma no ofrece una declaración explícita para decir que el uso de un valor indeterminado no está definido. La excepción son los iteradores y, por extensión, tenemos el concepto de valor singular y en la sección 24.2.1 se nos dice que:

[…] [Ejemplo: después de la declaración de un puntero no inicializado x (como con int * x;), siempre se debe suponer que x tiene un valor singular de un puntero. —En el ejemplo] […] Los valores que no se pueden referenciar siempre son no singulares.

y:

Un iterador no válido es un iterador que puede ser singular. 268

y la nota 268 dice:

Esta definición se aplica a los punteros, ya que los punteros son iteradores. El efecto de desreferenciar un iterador que ha sido invalidado no está definido.

En C ++ 1y el lenguaje cambia y tenemos una declaración explícita que hace que el uso de un valor intermedio no esté definido con algunas excepciones limitadas .