2012-07-15 17 views
13

Aclaración: Dado que una cadena literal puede ser reescrito como un const char[] (ver abajo), imponiendo una longitud max inferior en literales que en char[] s es sólo un inconveniente sintáctica. ¿Por qué el estándar C fomenta esto?¿Por qué la longitud máxima de la cadena C es literalmente diferente de la máxima char []?


El estándar C89 tiene un límite de traducción de cadenas literales:

509 caracteres en una cadena de caracteres literal de cadena o ancho literal (después de la concatenación)

No hay una límite para una matriz de caracteres; quizás

32767 bytes en un objeto (en un entorno alojado única)

se requiera (no estoy seguro de qué objeto o entorno alojado significa), pero en todo caso se trata de un límite mucho más alto.

Mi entendimiento es que una cadena literal es equivalente a personajes que contienen matriz de caracteres, es decir: siempre es posible volver a escribir algo como esto:

const char* str = "foo"; 

en este

static const char __THE_LITERAL[] = { 'f', 'o', 'o', '\0' }; 
const char* str = __THE_LITERAL; 

Entonces, ¿por ejemplo una límite duro en literales?

+6

Es muy extraño que hayan elegido 509 en lugar de 65533 o 253. –

+3

Le recomendamos leer este artículo: http://msdn.microsoft.com/en-us/library/sx08afx2.aspx –

+2

Límites en el programa * fuente * no tiene nada que ver con los límites en el programa compilado. –

Respuesta

14

El límite en literales de cadena es un requisito de tiempo de compilación; hay un límite similar en la longitud de una línea fuente lógica. Un compilador puede usar una estructura de datos de tamaño fijo para contener líneas fuente y literales de cadenas.

(C99 aumenta estos límites particulares de 509 a 4095 caracteres.)

Por otro lado, un objeto (como una matriz de char) se puede construir en tiempo de ejecución. Es probable que los límites sean impuestos por la arquitectura de la máquina objetivo, no por el diseño del compilador.

Tenga en cuenta que estos son no límites superiores impuestos a los programas. Un compilador no está obligado a imponer ningún límite finito. Si un compilador impone un límite en la longitud de la línea, debe tener al menos 509 o 4095 caracteres. (La mayoría de los compiladores reales, creo, no imponen límites fijos, sino que asignan la memoria de forma dinámica.)

+0

Aunque, por supuesto, hay un límite práctico: si el compilador es un ejecutable de 32 bits, ciertamente no podría manejar un literal de cadena sobre 4G (a pesar de las limitaciones del formato del archivo de objeto). El límite real de curso sería mucho menor. –

+0

¿No se construyó 'const char []' inicializado también en tiempo de compilación? – npostavs

+0

@npostavs: Puede ser, pero el límite de 32767 bytes (aumentado a 65536 en C99) se aplica a los objetos en tiempo de ejecución, independientemente de cómo se hayan construido. –

4

No es que 509 caracteres es el límite para una cadena, es el mínimo requerido para la compatibilidad ANSI, como se explica here.

Creo que los fabricantes de la norma sacaron el número 509 de su trasero, pero a menos que obtengamos documentación oficial de esto, no hay forma de que sepamos.

En cuanto a cuántos caracteres pueden estar realmente en una cadena literal, eso depende del compilador.

Éstos son algunos ejemplos:

  • MSVC: 2048
  • GCC: No Limit (hasta 100.000 caracteres), pero da advertencia después de 510 caracteres:

    literal de cadena de longitud 100000 excede la longitud máxima 509 que los compiladores C90 son necesarios para admitir

+0

Información interesante, pero en realidad no responde la pregunta. –

+0

@KeithThompson No estoy de acuerdo. Responde a la pregunta porque explica que no es un "límite", sino un "mínimo", por lo que en la mayoría de los compiladores, no habrá diferencia. –

+0

Creo que el punto clave es que el 509 al que se hace referencia en el estándar es un mínimo, no un máximo. –

0

Disculpa la respuesta tardía, pero me gustaría ilustrar la diferencia entre los dos casos (Richard J. Ross ya se ha señalado que no son equivalentes)

Supongamos que usted intenta esto:.

const char __THE_LITERAL[] = { 'f', 'o', 'o', '\0' }; 
const char* str = __THE_LITERAL; 
char *str_writable = (char *) str; // Not so const anymore 
str_writable[0] = 'g'; 

Ahora str contiene "goo".

Pero si usted hace esto:

const char* str = "foo"; 
char *str_writable = (char *) str; 
str_writable[0] = 'g'; 

Resultado: segfault! (en mi plataforma, al menos.)

Aquí está la diferencia fundamental: en el primer caso, usted tiene una matriz que se inicializa en "foo", pero en el segundo caso tiene un literal de cadena real.

En una nota lateral,

const char __THE_LITERAL[] = { 'f', 'o', 'o', '\0' }; 

es exactamente equivalente a

const char __THE_LITERAL[] = "foo"; 

Aquí los = actúa como un inicializador de matriz en lugar de como la asignación. Esto es muy diferente de

const char *str = "foo"; 

donde se asigna la dirección de la cadena literal a str.

+0

Oh, quise que __THE_LITERAL fuera una variable estática, en cuyo caso segfault resulta en ambos casos. – npostavs

+0

@npostavs: Hmm, tienes razón. Interesante. En realidad, estaba equivocado sobre el '=" foo "' siendo tratado exactamente como '= {'f', 'o', 'o', '\ 0'}'. Si hago lo mismo con más de 509 caracteres, gcc da una advertencia en el primer caso pero no en el segundo. Supongo que es por lo que Keith Thompson dijo antes: los compiladores pueden usar estructuras de datos de tamaño fijo para procesar literales. –

Cuestiones relacionadas