2012-09-22 34 views
11

Dada una matriz de punteros a cadenas literales:determinar la longitud de una cadena literal

char *textMessages[] = { 
    "Small text message", 
    "Slightly larger text message", 
    "A really large text message that " 
    "is spread over multiple lines" 
} 

¿Cómo se determina la longitud de una cadena literal particular, - dice la tercera? He intentado usar el comando sizeof de la siguiente manera:

int size = sizeof(textMessages[2]); 

Pero el resultado parece ser el número de punteros en la matriz, en lugar de la longitud de la cadena literal.

+3

'sizeof (textMessages [2])' dará el tamaño del tipo 'char *'. Es pura coincidencia que 'sizeof (char *)' sea 4 en su sistema, y ​​nada que ver con la cantidad de elementos en su matriz. –

+0

Debería considerar usar la definición 'static const char textMesssages [] [4]' para su matriz. –

+1

@MichaelFoukarakis Solo hay * tres * punteros en la matriz (tenga en cuenta la concatenación de cadenas). – Jens

Respuesta

17

Si desea que el número calculado en tiempo de compilación (a diferencia de en tiempo de ejecución con strlen) es perfectamente apropiado el uso de una expresión como

sizeof "A really large text message that " 
     "is spread over multiple lines"; 

Sin embargo, es posible que desee utilizar una macro para evitar repetir el literal largo:

#define LONGLITERAL "A really large text message that " \ 
        "is spread over multiple lines" 

Tenga en cuenta que el valor devuelto por sizeof incluye el NUL de terminación, por lo que es uno más que strlen.

+0

Deseo determinar la longitud de cada cadena para que pueda indexar las longitudes y pasarlas a una función. ¿Es posible calcular dicha matriz de longitudes en tiempo de compilación? – Zack

+1

Mi enfoque sería declarar e inicializar una matriz de 'struct {char * ptr; size_t len; } x [] '. Luego puede llamar a 'foo (x [i] .ptr, x [i] .len)'. Como C no mantiene las longitudes de las cuerdas, no hay otra manera que hacer un seguimiento de las longitudes de las cuerdas en su código. – Jens

0

strlen ¿quizás?

size_t size = strlen(textMessages[2]); 
+3

¿Por qué calcular este número en tiempo de ejecución cuando se puede determinar en tiempo de compilación? – Jens

+0

@Jens: No, a menos que también conozca la cadena en el momento de la compilación. – Tudor

+0

@Tudor, sí - usted sabe la longitud en tiempo de compilación (la pregunta dice "Cadena Literal") – ideasman42

0

se debe utilizar el método de strlen() biblioteca para obtener la longitud de una cadena. sizeof le dará el tamaño de textMessages[2], un puntero, que dependería de la máquina (4 bytes u 8 bytes).

+0

¿No quiere decir 4 u 8 bytes? A menos que tenga una máquina de 16 bits ... – Tudor

+0

correcta, gracias por corregir :) – Vikdor

0

strlen le da la longitud de la cuerda mientras que sizeof devolverá el tamaño del tipo de datos en bytes que ha introducido como parámetro.

strlen

sizeof

-1

Te diré algo, según mis arrays de conocimiento, los punteros son lo mismo excepto cuando usas sizeof.

Cuando se utiliza sizeof en un puntero se volverá siempre 4 BYTE sin importar lo que apunta el puntero, pero si se utiliza en la matriz se volverá ¿Por cuánto tiempo la matriz es grande en bytes?.

En que ejemplo de ello es *textMessage[] conjunto de puntero de modo que cuando se utiliza sizeof(textMessage[2]) volverá 4 BYTE porque textMessage[2] es un puntero.

Espero que sea útil para usted.

+0

No entendí lo que quiere –

+0

Mi intención fue decirle que mejore su conocimiento sobre la ** diferencia ** de matrices y punteros leyendo todo http://c-faq.com/aryptr/index.html Las matrices no son punteros y suelen ser 2 u 8 en lugar de 4 bytes y su tamaño puede depender del tipo que señalan. Entonces, la mayor parte de lo que escribiste es técnicamente incorrecto. – Jens

+0

Bien, gracias @jens –

0

Se podría explotar el hecho, de que los valores de una matriz son consecutivas:

const char *messages[] = { 
    "footer", 
    "barter", 
    "banger" 
}; 

size_t sizeOfMessage1 = (messages[1] - messages[0])/sizeof(char); // 7 (6 chars + '\0') 

El tamaño se determina mediante el uso de los límites de los elementos.El espacio entre el comienzo del primer y el comienzo del segundo elemento es el tamaño del primero.

Esto incluye la terminación \0. La solución, por supuesto, solo funciona correctamente con cadenas constantes. Si las cadenas hubieran sido punteros, obtendría el tamaño de un puntero en lugar de la longitud de la cadena.

No se garantiza que funcione. Si los campos están alineados, esto puede producir tamaños incorrectos y puede haber otras advertencias introducidas por el compilador, como la fusión de cadenas idénticas. También necesitará al menos dos elementos en su matriz.

+3

Esto no está garantizado para funcionar. Si bien los punteros en la matriz deben ser consecutivos, los literales de cadena no necesitan. Piensa en la alineación y tal. O usando el mismo puntero para literales de cadena idénticos. – Jens

+0

Tiene razón, la alineación rompería esto (pero eso es controlable). Los diferentes tamaños para 'char' también romperían esto. Marcaré mi respuesta como no confiable. – nemo

+1

Fusionar cadenas idénticas, una optimización común, también lo rompe. – Jens

11

Mi sugerencia sería utilizar strlen y activar las optimizaciones del compilador.

Por ejemplo, con gcc 4.7 en x86:

#include <string.h> 
static const char *textMessages[3] = { 
    "Small text message", 
    "Slightly larger text message", 
    "A really large text message that " 
    "is spread over multiple lines" 
}; 

size_t longmessagelen(void) 
{ 
    return strlen(textMessages[2]); 
} 

Después de ejecutar make CFLAGS="-ggdb -O3" example.o:

$ gdb example.o 
(gdb) disassemble longmessagelen 
    0x00000000 <+0>: mov $0x3e,%eax 
    0x00000005 <+5>: ret 

es decir el compilador ha reemplazado la llamada a strlen con el valor constante 0x3e = 62.

¡No pierda el tiempo realizando optimizaciones que el compilador puede hacer por usted!

Cuestiones relacionadas