structures significado pointer objects data array c++ syntax reference pointers

significado - Cadenas de C++:[] vs.*



pointers in c (6)

He estado pensando, ¿cuál es la diferencia entre declarar una variable con [] o *? La manera en que lo veo:

char *str = new char[100]; char str2[] = "Hi world!";

.. debería ser la principal diferencia, aunque no estoy seguro si puedes hacer algo como

char *str = "Hi all";

.. dado que el puntero debería hacer referencia a un miembro estático, que no sé si puede?

De todos modos, lo que realmente me molesta es saber la diferencia entre:

void upperCaseString(char *_str) {}; void upperCaseString(char _str[]) {};

Entonces, ¿sería muy apreciado si alguien pudiera decirme la diferencia? Tengo la corazonada de que ambos podrían compilarse de la misma manera, excepto en algunos casos especiales.

Ty


Como complemento a las respuestas ya dadas, debe leer las preguntas frecuentes de C sobre matrices y punteros . Sí, es una pregunta frecuente en C y no una pregunta frecuente sobre C ++, pero hay poca diferencia sustancial entre los dos idiomas en esta área.

Además, como nota al margen, evite nombrar sus variables con un guion bajo. Eso está reservado para los símbolos definidos por el compilador y la biblioteca estándar.


De acuerdo, había dejado dos comentarios negativos. Eso no es realmente útil; Los eliminé

  • El siguiente código inicializa un puntero char, apuntando al inicio de una porción de memoria asignada dinámicamente (en el montón).

char *str = new char[100];

Este bloque se puede liberar usando delete [] .

  • El siguiente código crea una matriz char en la pila, inicializada al valor especificado por un literal de cadena.

char [] str2 = "Hi world!";

Esta matriz se puede modificar sin problemas, lo cual es bueno. Asi que

str2[0] = ''N''; cout << str2;

debería imprimir Ni world! a la salida estándar, haciendo que ciertos caballeros se sientan muy incómodos.

  • El siguiente código crea un puntero de char en la pila, apuntando a un literal de cadena ... El puntero puede reasignarse sin problemas, pero el bloque de punta no se puede modificar (este es un comportamiento indefinido; segfaults en Linux, por ejemplo).

char *str = "Hi all"; str[0] = ''N''; // ERROR!

  • Las siguientes dos declaraciones

void upperCaseString(char *_str) {}; void upperCaseString(char [] _str) {};

me parece igual, y en su caso (quiere mayúsculas una cadena en su lugar) realmente no importa.

Sin embargo, todo esto plantea la pregunta: ¿por qué estás usando char * para expresar cadenas en C ++?


La primera opción asigna dinámicamente 100 bytes.

La segunda opción asigna de forma estática 10 bytes (9 para el carácter de cadena + nulo).

Su tercer ejemplo no debería funcionar: está intentando llenar de forma estática un elemento dinámico.

En cuanto a la pregunta upperCaseString() , una vez que la C-string ha sido asignada y definida, puede iterar a través de indexación de matriz o mediante notación de puntero, porque una matriz es realmente una forma conveniente de ajustar la aritmética de puntero en C.

(Esa es la respuesta simple: espero que alguien más tenga la respuesta autorizada y complicada de la especificación :))


Las tres declaraciones diferentes permiten que el puntero apunte a diferentes segmentos de memoria:

char* str = new char[100];

Vamos a apuntar al montón.

char str2[] = "Hi world!";

pone la cadena en la pila.

char* str3 = "Hi world!";

apunta al segmento de datos.

Las dos declaraciones

void upperCaseString(char *_str) {}; void upperCaseString(char _str[]) {};

son iguales, el compilador se queja de que la función ya tiene un cuerpo cuando intenta declararlos en el mismo ámbito.



Veámoslo (para lo siguiente, note que char const y const char son los mismos en C ++):

Cadenas literales y char *

"hello" es una matriz de 6 caracteres const: char const[6] . Como cada matriz, puede convertir implícitamente en un puntero a su primer elemento: char const * s = "hello"; Para la compatibilidad con el código C, C ++ permite otra conversión, que de otro modo estaría mal formada: char * s = "hello"; elimina la const !. Esta es una excepción, para permitir la compilación de ese código C-ish, pero está en desuso para hacer un punto char * a un literal de cadena. Entonces, ¿qué tenemos para char * s = "foo"; ?

"foo" -> array-to-pointer -> char const* -> qualification-conversion -> char * . Un literal de cadena es de solo lectura y no se asignará en la pila. Puedes hacerles un puntero libremente, y regresar ese de una función, sin chocar :).

Inicialización de una matriz usando un literal de cadena

Ahora, ¿qué es char s[] = "hello"; ? Es una cosa completamente diferente. Eso creará una matriz de caracteres y lo llenará con la cadena "hello" . El literal no es apuntado. En su lugar, se copia a la matriz de caracteres. Y la matriz se crea en la pila . No puede devolver un puntero válidamente desde una función.

Tipos de parámetros de matriz.

¿Cómo puede hacer que su función acepte una matriz como parámetro? Usted declara que su parámetro es una matriz:

void accept_array(char foo[]);

pero omites el tamaño. En realidad, cualquier tamaño lo haría, ya que simplemente se ignora: el estándar dice que los parámetros declarados de esa manera se transformarán para ser lo mismo que

void accept_array(char * foo);

Excursión: matrices multidimensionales

Sustituir char por cualquier tipo, incluidas las matrices en sí:

void accept_array(char foo[][10]);

acepta una matriz de dos dimensiones, cuya última dimensión tiene el tamaño 10. ¡ El primer elemento de una matriz multidimensional es su primera sub-matriz de la siguiente dimensión ! Ahora, vamos a transformarlo. Será un puntero a su primer elemento de nuevo. Por lo tanto, en realidad aceptará un puntero a una matriz de 10 caracteres: (quite el [] en la cabeza, y luego simplemente haga un puntero al tipo que ve en su cabeza):

void accept_array(char (*foo)[10]);

Como las matrices convierten implícitamente en un puntero a su primer elemento, puede pasar una matriz bidimensional (cuyo último tamaño de dimensión es 10) y funcionará. De hecho, ese es el caso para cualquier matriz n-dimensional, incluido el caso especial de n = 1 ;

Conclusión

void upperCaseString(char *_str) {};

y

void upperCaseString(char _str[]) {};

son lo mismo, ya que el primero es solo un puntero a char. Pero tenga en cuenta que si desea pasar un literal String a eso (digamos que no cambia su argumento), entonces debe cambiar el parámetro a char const* _str para no hacer cosas obsoletas.