2011-06-04 12 views
11

Hablando de los literales de cadena, el estándar C99 dice (6.4.5.6):En C, ¿se garantiza que las variables const serán distintas en la memoria?

Es sin especificar si estas matrices son distintos siempre que sus elementos tienen los valores apropiados. Si el programa intenta modificar dicha matriz, el comportamiento no está definido.

No pude encontrar ni una advertencia similar ni una garantía explícita para las variables const. ¿Puede la expresión &x == &y en el contexto const int x=12; const int y=12; evaluar a 1? ¿Qué pasa con una variable const y un literal de cadena (es decir, &x == "\014\000\000" con la garantía de ser 0 incluso en una plataforma little-endian de 32 bits)?

Por lo que vale, la sección "Cadenas literales" en this blog post da el contexto de la pregunta.

+0

Tenga en cuenta que sólo se emitirá gcc '' x' y y' si se pueden tomar sus direcciones, y en ese caso, los emite en diferentes direcciones. – ninjalj

+2

Vea también: [Análisis profundo de Const Calificador en C] (http://stackoverflow.com/questions/4275504/deep-analysis-of-const-qualifier-in-c) –

Respuesta

5

En el estándar, la igualdad se discute en §6.5.9 “Operadores de igualdad”, & se discute en §6.5.3.2 “operadores de dirección y de indirección”, y const se discute en §6.7.3 “Tipo calificadores”. El pasaje relevante sobre la igualdad del puntero es §6.5.9.6:

dos punteros comparan iguales si y sólo si ambos son punteros nulos, ambos son punteros a la mismo objeto (incluyendo un puntero a un objeto y un subobjeto en su comienzo) o función, [o punteros pasado el final de una matriz]

la única definición de & es que “el & operador unario produce la dirección de su operando. [...] El resultado es un puntero al objeto o función designado por su operando. "(§6.5.3.2.3). Lamentablemente, no existe una definición formal de la palabra "dirección"; pero los objetos distintos (para la igualdad definida por ==) tienen direcciones distintas, porque las direcciones son punteros que son distintos por la definición de igualdad anterior.

En cuanto al significado de const, el §6.7.3 no indica que const tenga alguna relación con lo que crea un objeto (que es "una región de almacenamiento de datos en el entorno de ejecución, cuyos contenidos pueden representar valores "Por §3.14). Una nota al pie de página indica además que "la implementación no necesita asignar almacenamiento para tal objeto si su dirección nunca se usa". Aunque esto no es normativo, es una fuerte indicación de que si se usa la dirección, entonces el almacenamiento debe asignarse para cada objeto.

Tenga en cuenta que si los objetos son const volatile, entonces es bastante claro (tan claro como volatile puede ser nunca) que no pueden tener la misma dirección, porque const volatile objetos son mutables por la implementación. (§6.7.3.10 tiene un ejemplo de uso de const volatile.)

Incluso en el caso no volátil, const sólo indica que esta parte del programa no está autorizado a modificar el objeto, no es que el objeto es lectura solo en general. Para combinar el almacenamiento de un objeto const con otra cosa, el implementador audaz debería garantizar que nada puede modificar el objeto. Esto es bastante difícil para un objeto con enlace externo en una implementación con compilación separada (pero, por supuesto, nos estamos alejando del estándar y entramos en el territorio de la práctica no va a suceder).

Si esto es acerca de cómo escribir un programa en C, entonces se puede aumentar sus posibilidades dando a los objetos de valores diferentes:

const int x = __LINE__; 
const int y = __LINE__; 

Si esto se trata de un modelo teórico de C, me gustaría ir para hacer el objetos distintos. Tendrás que justificar esta elección resumiendo las respuestas aquí en un párrafo en (la versión extendida de) tu artículo.

Por otro lado, si se trata de escribir un compilador de optimización, dudo que perjudique a muchos programas del mundo real fusionar constantes. Me gustaría fusionarme en un compilador incrustado, donde los usuarios están acostumbrados a jugar a lo seguro con casos extremos y donde la memoria guardada podría ser no despreciable. Iría contra la fusión en una plataforma alojada donde cualquier ganancia sería insignificante.

(Referencias de N1256 también conocido como C99 + TC3. Yo no creo que la versión marca una diferencia.)

+0

Seguramente si va a implementar una optimización no conforme, incluso en un objetivo incrustado, debe hacer que se apague y encienda. En cuyo caso, suponiendo que exista demanda en cualquier lugar, también puede ofrecerlo para todos los objetivos, y dejar que el usuario decida si romperá su programa y si necesitan guardar el espacio. –

+0

Me gustan tus argumentos, pero con respecto a tu párrafo "Incluso ..." en la constante no volátil, 'GCC' compila' const int x = 12; int y; main() { y = x; f(); y + = x; printf ("% d \ n", y); } 'into 'movl \t $ 12, ...' y 'addl \t $ 12, ...', asumiendo que 'f()' no cambia la variable constante 'x' (supone que' f() 'puede cambiar' y' , sin embargo. –

+0

@Pascal: para que esta prueba sea confiable, debe convencer a gcc de que se toma la dirección de 'x', es decir, tener' & x' en algún lugar donde no se optimice. También necesita convencer a gcc de que no sabe si 'f' podría ver' x'; tener 'x' be' extern' y 'f' definido en otro archivo debería hacerlo. – Gilles

6

Que yo sepa, el Estándar no permite que dos objetos con nombre de ningún tipo tengan la misma dirección (excepto para los miembros del sindicato). Desde 6.5.9/6:

dos punteros comparan iguales si y sólo si ambos son punteros nulos, ambos son punteros al mismo objeto ...

literales de cadena no son variables const entonces su pregunta secundaria es discutible, y no veo qué tienen que ver con 32 bits y endianness.

+0

Bien, haga la segunda pregunta sobre ' const char t [4] = {'a', 'b', 'c'}; 'y' "abc" 'si lo prefiere. –

+2

Lo que tienen que ver con esto es que la representación del objeto de 'x' (un número entero 12) ocurre en una plataforma little-endian de 32 bits para contener los mismos bytes que la representación del objeto de la cadena literal' "\ 014 \ 000 \ 000 "'. Así que creo que parte de la pregunta es si el literal de la cadena se puede doblar en 'x', o si los literales de cadena solo se pueden plegar en otros literales de cadena. –

+0

@Steve Oh, ya veo. Gracias. @Pascal Bueno, hasta donde yo sé, el Estándar solo dice que los valores pueden ser indistintos para los literales de cadenas. Pero es un poco difícil proporcionar evidencia de un negativo. –

3

En

const int x=12; 
const int y=12; 

x y y son diferentes variables (tanto const cualificado) y por lo tanto tienen diferentes direcciones.

Lo mismo para el otro ejemplo.

Tenga en cuenta que const es un calificador para un objeto. En cuanto al diseño de la memoria, no importa si está allí o no.

1

6.4.5/6 dice de las matrices correspondientes a los literales de cadena:

Es especi fi ed si estas matrices son distintos proporcionan sus elementos tienen los valores apropiados.

Así que esa es una norma específica que permita a los literales de cadena pueden plegar. No sé nada en el estándar que diga lo mismo para otros objetos.

Cuestiones relacionadas