2009-09-27 7 views
11

digamos que tenemos una matriz de punteros de char¿La matriz de caracteres * debe terminar en ' 0' o en ' 0'?

char* array[] = { "abc", "def" }; 

Ahora lo que deben ser puestas en el final?

char* array[] = { "abc", "def", '\0' }; 

o

char* array[] = { "abc", "def", "\0" }; 

Sin embargo, ambas obras. Sólo tenemos que poner la condición de comprobar el final en consecuencia

como

array[ index ] != '\0'; 

o

array[ index ] != "\0"; 

Mi pregunta es cuál es la mejor manera? ¿Cuál es utilizado por la mayoría de los programadores?

Editar

mayoría de las respuestas dicen que NULL es mejor que '\ 0' y "\ 0". Pero siempre he pensado que

NULL es igual a '\ 0', que es igual a 0x0 ó 0

¿Está mal?

+1

En cuanto a la edición, In C NULL es un puntero (generalmente definido (void *) 0. '\ 0' es una constante de caracteres. Por lo tanto, cuando se utiliza una constante de caracteres donde se espera un puntero y se produce una conversión implícita. sucede la conversión de cualquier resultado entero cero en un puntero NULL, pero no deja en claro que usted tenía la intención de utilizar un puntero. Es mejor simplemente usar un entero constante literal IMO cero. Como ocurre en C++ este es el enfoque preferido en cualquier caso, pero en C++ la macro NULL también se define de esa manera (eche un vistazo a los archivos de encabezado estándar de su compilador). – Clifford

Respuesta

24

Lo terminaría con NULL. ¿Por qué? Porque no se puede hacer ninguna de estas:

array[index] == '\0' 
array[index] == "\0" 

La primera de ellas es la comparación de un char * a un char, que es no lo desea. Tendría que hacer esto:

array[index][0] == '\0' 

El segundo ni siquiera funciona. Está comparando un char * con un char *, sí, pero esta comparación no tiene sentido. Pasa si los dos punteros apuntan a la misma pieza de memoria. No puede usar == para comparar dos cadenas, tiene que usar la función strcmp(), porque C no tiene soporte integrado para cadenas fuera de unos pocos (y me refiero a pocas) sutilezas sintácticas. Mientras que el siguiente:

array[index] == NULL 

Funciona bien y transmite su punto de vista.

+0

. En realidad, la comparación 'char *' probablemente funcionó para el OP, ya que el compilador unificó los dos literales de cadena idénticos. Estoy de acuerdo en que la comparación no tiene sentido, en principio. –

+0

Sé que probablemente funcionó, pero de ninguna manera está garantizado que funcione, y nunca se debe confiar en él, y por lo tanto no tiene sentido. Si funciona, funciona porque tienes un compilador inteligente o porque tienes suerte. –

+1

¿NULL no es lo mismo que '\ 0'? Lo que entiendo es que NULL == '\ 0' == 0x0. ¿Es incorrecto? –

0

Bueno, técnicamente '\0' es un carácter, mientras que "\0" es una cadena, por lo que si está buscando el carácter de terminación nula, el primero es el correcto. Sin embargo, como Chris Lutz points out in his answer, su comparación no funcionará en su forma actual.

+0

Usar ''\ 0'' es comparar un' char * 'con un' char' que es como comparar manzanas a naranjas. Tampoco es correcto, realmente. –

+1

@Chris: usando ''\ 0'' está comparando un' char * 'con un' int' Christoph

+0

@Christoph - eso es lo que Chris Lu Tz señaló.En lugar de actualizar mi respuesta, señalé mi respuesta en – ChrisF

5

De estos dos, el primero es un error de tipo: '\ 0' es un caracter, no un puntero. El compilador todavía lo acepta porque puede convertirlo en un puntero.

El segundo "funciona" solo por coincidencia. "\ 0" es un literal de cadena de dos caracteres. Si se producen en varios lugares en el archivo fuente, el compilador puede, aunque no necesariamente, hacerlos idénticos.

Así que la forma correcta de escribir el primero es

char* array[] = { "abc", "def", NULL }; 

y se prueba para array[index]==NULL. La forma correcta de probar el segundo es array[index][0]=='\0'; también puede soltar el '\ 0' en la cadena (es decir, deletrearlo como "") ya que eso ya incluirá un byte nulo.

+0

Me resulta interesante que este problema tenga dos respuestas que funcionen, pero ninguna de las dos es técnicamente correcta, y ninguna de las dos funciona por el motivo que OP cree que tienen. –

0

La terminación de una matriz de caracteres con un carácter nulo es solo una convención que es específicamente para cadenas en C. Se trata de algo completamente diferente - una matriz de punteros de caracteres - por lo que realmente no tiene relación con la convención para cadenas de C Claro, podrías elegir terminarlo con un puntero nulo; que tal vez podría ser su convención para arreglos de punteros. Hay otras formas de hacerlo. No puede preguntarle a la gente cómo "debería" funcionar, porque está asumiendo alguna convención que no está allí.

+0

La convención está ahí para las matrices de longitud variable: use NULL como valor centinela. – u0b34a0f6ae

6

De acuerdo con la especificación C99,

  • NULL expande a una constante puntero nulo, lo que no se requiere para ser, pero típicamente es de tipo void *
  • '\0' es una constante de caracteres; las constantes de caracteres son de tipo int, por lo que es equivalenciadet a llanura 0
  • "\0" es una cadena terminada en cero literal y equivalentes al compuesto literal (char [2]){ 0, 0 }

NULL, '\0' y 0 son todas las constantes de puntero nulo, por lo que todos arrojarán punteros nulos en la conversión, mientras que "\0" arroja un char * no nulo (que debe tratarse como const ya que la modificación no está definida); como este puntero puede ser diferente para cada ocurrencia del literal, no puede usarse como valor centinela.

Aunque se puede utilizar cualquier número entero constante expresión de valor 0 como una constante puntero nulo (por ejemplo '\0' o sizeof foo - sizeof foo + (int)0.0), se debe utilizar NULL para hacer sus intenciones claras.

+0

Aunque para ser * realmente * nit picking, 'NULL' se expande a un puntero nulo solo en caso de que se defina como' (void *) 0' (en cuyo caso es tanto eso como una constante de puntero nulo) :) Si sucede ser '0' o similar, entonces solo es una constante de puntero nulo, que aún tiene que convertirse en un puntero nulo :) –

+0

@litb: en realidad,' '\ 0'' podría no ser una constante de puntero nulo válida ya que una constante de caracteres (C99 6.4.4.4) y no una constante entera (C99 6.4.4.1); las constantes de caracteres a veces se llaman constantes de caracteres enteros, pero ¿eso los convierte en una "expresión constante constante" según lo requerido por C99 6.3.2.3? – Christoph

+0

@Christop 6.6/6 :) –

-1

La terminación nula es un mal diseño que queda mejor en los libros de historia. Todavía hay mucha inercia detrás de c-strings, por lo que no se puede evitar allí. Pero no hay ninguna razón para usarlo en el ejemplo del PO.

No utilice ningún terminador, y use sizeof (array)/sizeof (array [0]) para obtener la cantidad de elementos.

+1

+1 para sizeof array/sizeof array [0]. ¿Pero crees que es motivo suficiente para no usar Terminator? –

+1

esto solo funciona si la matriz se declara en el ámbito: si se pasa por un puntero, no se puede hacer 'sizeof (array)' y solo se puede obtener la longitud pasando el tamaño mediante un parámetro o buscando el terminador nulo . –

+0

Debería haber sido más claro. Pase la cantidad de elementos a lo largo del lado de su matriz. Más seguro y más claro que usar un terminador. – Alan

Cuestiones relacionadas