válido variable valor una siguientes siguiente programacion nombre literales literal las extraer enteros ejemplos cuál caracteres cadenas cadena c++ c literals string-literals

c++ - variable - ¿Por qué los literales de cadena son de valor l, mientras que todos los demás literales tienen valor r?



¿cuál de las siguientes cadenas es un nombre de variable válido ? (4)

C ++ 03 5.1 Expresiones primarias
§2:

Un literal es una expresión primaria. Su tipo depende de su forma (2.13). Un literal de cadena es un lvalue; Todos los demás literales son valores.

¿Cuál es la razón detrás de esto?
Según tengo entendido, los literales de cadena son objetos, mientras que los otros literales no lo son. Y un valor l siempre se refiere a un objeto.

Pero la pregunta entonces es ¿por qué son objetos literales de cadena mientras que los otros literales no lo son?
Este razonamiento me parece más a un problema de huevo o pollo.

Entiendo que la respuesta a esto puede estar relacionada con la arquitectura de hardware en lugar de C / C ++ como lenguajes de programación, sin embargo, me gustaría escuchar lo mismo.

Nota: estoy etiquetando esta pregunta como c & c ++ porque el estándar C99 también tiene citas similares, específicamente §6.5.1.4


Los literales de cadena son matrices , objetos de tamaño inherentemente impredecible (es decir, de tamaño definido por el usuario y posiblemente de gran tamaño). En el caso general, simplemente no hay otra forma de representar tales literales, excepto como objetos en la memoria, es decir, como lvalues . En C99 esto también se aplica a los literales compuestos , que también son lvalues .

Cualquier intento de ocultar artificialmente el hecho de que los literales de cadena son lvalues de lvalues en el nivel del idioma produciría un número considerable de dificultades completamente innecesarias, ya que la capacidad de apuntar a un literal de cadena con un puntero, así como la capacidad de acceder a ella como una matriz depende críticamente en su valor de ser visible a nivel de lenguaje.

Mientras tanto, los literales de tipos escalares tienen un tamaño de tiempo de compilación fijo. Al mismo tiempo, es muy probable que dichos literales estén integrados directamente en los comandos de la máquina en la arquitectura de hardware dada. Por ejemplo, cuando escribe algo como i = i * 5 + 2 , los valores literales 5 y 2 convierten en partes explícitas (o incluso implícitas) del código de máquina generado. No existen y no necesitan existir como ubicaciones independientes en el almacenamiento de datos. Simplemente no tiene sentido almacenar los valores 5 y 2 en la memoria de datos.

También vale la pena señalar que en muchos (si no en la mayoría, o en todos) las arquitecturas de hardware, los literales de punto flotante se implementan como lvalues "ocultos" (aunque el lenguaje no los expone como tales). En plataformas como la máquina x86, los comandos del grupo de punto flotante no admiten operandos inmediatos incrustados. Esto significa que virtualmente cada literal de punto flotante tiene que ser almacenado (y leído) en la memoria de datos por el compilador. Por ejemplo, cuando escribes algo como i = i * 5.5 + 2.1 se traduce en algo como

const double unnamed_double_5_5 = 5.5; const double unnamed_double_2_1 = 2.1; i = i * unnamed_double_5_5 + unnamed_double_2_1;

En otras palabras, floating-point literals menudo terminan convirtiéndose en lvalues "no oficiales" internamente. Sin embargo, tiene mucho sentido que la especificación del lenguaje no haya intentado exponer este detalle de implementación. A nivel de lenguaje, arithmetic literals tienen más sentido como rvalues .


Supongo que el motivo original era principalmente pragmático: una cadena literal debe residir en la memoria y tener una dirección. El tipo de una cadena literal es un tipo de matriz ( char[] en C, char const[] en C ++), y los tipos de matriz se convierten en punteros en la mayoría de los contextos. El lenguaje podría haber encontrado otras formas de definir esto (por ejemplo, un literal de cadena podría tener un tipo de puntero, con reglas especiales con respecto a lo que apuntaba), pero hacer que el literal sea un valor l es probablemente la forma más fácil de definir lo que es concretamente necesario.


Un literal de cadena es un literal con tipo de matriz, y en C no hay forma de que exista un tipo de matriz en una expresión, excepto como un valor l. Los literales de cadena se podrían haber especificado para que tuvieran un tipo de puntero (en lugar de un tipo de matriz que generalmente se descompone en un puntero) que apunta a la "contenido" de la cadena, pero esto los haría bastante menos útiles; en particular, el operador sizeof no podría ser aplicado a ellos.

Tenga en cuenta que C99 introdujo literales compuestos, que también son valores l, por lo que tener un valor literal es un valor ya no es una excepción especial; Está más cerca de ser la norma.


Un valor lvalue en C ++ no siempre se refiere a un objeto. Puede referirse a una función también. Además, los objetos no tienen que ser referidos por lvalues . Pueden ser referidos por rvalues , incluyendo para arreglos (en C ++ y C). Sin embargo, en el antiguo C89, la conversión de matriz a puntero no se aplicaba a las matrices de rvalues .

Ahora, un rvalue denota no, limitado o pronto será una vida caducada. Una cadena literal, sin embargo, vive para todo el programa.

Entonces, string literals son lvalues son exactamente correctos.