2012-05-24 8 views
5

así lo hice la siguiente prueba:literales de cadena que contienen ' 0' - por qué no son lo mismo?

char* a = "test"; 
char* b = "test"; 
char* c = "test\0"; 

Y ahora las preguntas:

1) ¿Es garantizado que a==b? Sé que estoy comparando direcciones. Esto no pretende comparar las cadenas, sino si se almacenan literales idénticos en una sola ubicación de memoria

2) ¿Por qué no a==c? ¿No debería el compilador ver que se están refiriendo a la misma cadena?

3) ¿Hay un \0 adicional al final de c, a pesar de que ya contiene uno?

no quería que pedir 3 preguntas diferentes para este, ya que parecen relacionados de alguna manera, lo siento 'combate que.

Nota: La etiqueta es correcta, estoy interesado en C++. (Aunque por favor, especifique si el comportamiento es diferente de C)

+7

Debe ser 'char const * a = ...'. –

+0

ayb tienen el mismo valor, pero eso no significa necesariamente que sean la cadena _same_. –

+0

@HunterMcMillen - en realidad eso es exactamente lo que significaría. –

Respuesta

18

personal ¿Se garantiza que a == b?

No. Pero es permitido por §2.14.5/12:

Si todos los literales de cadena son distintos (es decir, que se almacenan en los objetos que no se superponen) es definido por la implementación. El efecto de intentar modificar un literal de cadena no está definido.

y como se puede ver a partir de esta última frase usando en lugar de char*char const* es una receta para problemas (y su compilador debe rechazarla; asegúrese de que tiene habilitadas las advertencias y los altos niveles de conformidad seleccionados).

¿Por qué no a == c? ¿No debería el compilador ver que se están refiriendo a la misma cadena?

No, no es necesario que se refieran a la misma matriz de caracteres. Uno tiene cinco elementos, los otros seis. Una implementación podría almacenar los dos en el almacenamiento superpuesto, pero eso no es obligatorio.

¿Hay un \ 0 agregado al final de c, a pesar de que ya contiene uno?

Sí.

+0

También podría valer la pena explicar que '" test "' es un literal 'char const [5]' en el contexto de por qué A & B * puede * superponerse pero C no. – AJG85

+0

Gracias. Una pregunta más. Si uso 'strcmp' para comparar' a' y 'c', ¿dirá que son iguales? Además, ¿está permitido para 'a == c'? – AMCoder

+0

@ AJG85 ¿por qué no se superpone 'c'? El estándar lo permite explícitamente (la cita está en la respuesta y no se limita a literales idénticos), y un programa no puede distinguir la diferencia sin invocar un comportamiento indefinido. –

6

1 - absolutamente no. a might == b aunque si el compilador elige compartir la misma cadena estática.

2 - debido a que no se refieren a la misma cadena

3 - sí.

El comportamiento no es diferente entre C y C++ aquí, excepto que los compiladores de C++ debe rechazar la asignación de carbón no constante *.

+0

La conversión de cadena literal a 'char *' está en desuso, pero no está prohibida en C++. –

+0

@james está prohibido en C++ 11 –

+0

@ JohannesSchaub-litb: ¡De ninguna manera! Esa es la mejor noticia que he escuchado todo el día. g ++ 4.7, clang 3.1 y VC11 aceptan la conversión, pero espero con impaciencia el día en que no :-) –

2

El problema aquí es que está mezclando los conceptos de puntero y equivalencia textual.

Cuando dice a == b o a == c pregunta si los punteros implicados apuntan a la misma dirección física. La prueba no tiene nada que ver con el contenido textual de los punteros.

Para obtener la equivalencia textual se debe utilizar strcmp

+0

Tenga en cuenta que 'strcmp' se detendrá en el * primer * cero, por lo que las cadenas' a' y 'c' se compararán igual a pesar de que una es más larga que la otra. –

+0

@MarkRansom es longitud equivalente en el sentido textual, que es lo que strcmp considerará. Tal vez debería expandir mi respuesta a los 3 reinos que pueden ser importantes aquí: equivalencia de puntero, equivalencia de texto y equivalencia de memoria – JaredPar

+0

-1 lo siento pero tengo una comparación de puntero porque quiero comparar punteros. De eso se trata la pregunta. – AMCoder

4

1) ¿Se garantizó que a == b?

No lo es. Tenga en cuenta que está comparando direcciones y que podrían estar apuntando a diferentes ubicaciones. La mayoría de los compiladores inteligentes doblarán esta constante literal duplicada, por lo que los punteros pueden comparar igual, pero nuevamente no está garantizado por el estándar.

2) ¿Por qué no a == c? ¿No debería el compilador ver que se están refiriendo a la misma cadena?

Está tratando de comparar punteros, apuntan a diferentes ubicaciones de memoria. Incluso si comparas el contenido de esos indicadores, siguen siendo desiguales (consulta la siguiente pregunta).

3) ¿Hay un \ 0 añadido al final de c, a pesar de que ya contiene uno?

Sí, la hay.

+0

Sé que estoy comparando direcciones, ergo la pregunta. Para aclarar la pregunta: ¿hay literales de cadena idénticos ubicados en la misma memoria? – AMCoder

+0

Supongo que los punteros para 'a' y' c' pueden ser iguales. Un programa no puede notar la diferencia sin invocar a UB. –

+0

@R. Martinho Fernandes: Ese es un buen punto, creo que tienes razón. –

0

Si usted está haciendo comparaciones puntero que una! = B, b! = C, y c! = A. A menos que el compilador sea lo suficientemente inteligente como para notar que sus dos primeras cadenas son iguales.

Si lo hace un strcmp (str, str) entonces todas sus cadenas volverán como coincidencias.

no estoy seguro de si el compilador añadirá una terminación nula adicional a C, pero yo supongo que lo haría.

3

en primer lugar que este debe ser const char * ya que es lo literales de cadena a la caries.

  1. Ambos crean matrices inicializadas con 't' 'e' 's' 't' seguido de '\ 0' (longitud = 5). Comparando por la igualdad solo le dirá si ambos comienzan con el mismo puntero, no si tienen los mismos contenidos (aunque lógicamente, las dos ideas se suceden).
  2. A no es igual a C porque se aplican las mismas reglas, a = 't' 'e' 's' 't' '\ 0' y b = 't' 'e' 's' 't' ' \ 0 '' \ 0 '
  3. Sí, el compilador siempre lo hace y no debería funcionar explícitamente si está creando una cadena como esta. Sin embargo, si embaló una matriz y la llenó manualmente, debe asegurarse de agregar la \ 0.

Tenga en cuenta que para mi # 3, const char [] = "Hello World" también obtendría automáticamente el \ 0 al final, me refirió a llenar manualmente la matriz, sin que el compilador la resolviera.

+0

No creo que 'a' y' c' estén garantizados desiguales. El estándar permite que la implementación almacene literales en el almacenamiento superpuesto, y los programas no pueden notar la diferencia sin invocar a UB. –

+0

De hecho estoy de acuerdo con que habiendo verificado eso, fue un punto interesante que no había escuchado. Mi punto aún sería que el compilador definitivamente colocaría dos terminadores nulos en el caso 2, lo que hace que las operaciones sean desiguales, incluso si leer las cadenas y verificar sus punteros sería igual. Además, si registraste la longitud de la cadena que creaste para c, podrías leer con seguridad el strlen() por 1 y no podrías hacer una (a menos que estén en la misma ubicación que dijiste, pero no lo harías ser capaz de garantizar eso). –

+0

* Incluso si el compilador los almacenó en la misma ubicación *, 'a [5]' (que intenta leer el valor en la misma ubicación que 'c [5]') invocaría un comportamiento indefinido, porque 'a' apunta a una matriz de tamaño 5. No importa que haya otra matriz en el mismo lugar. –

0

Como se ha dicho algunas veces en otras respuestas, está comparando punteros.Sin embargo, agregaría que strcmp(b,c) debería ser cierto, porque deja de verificarse en el primer \0.

Cuestiones relacionadas