¿Cuál es la diferencia entre char a[] = ?cadena?; y char *p = ?cadena?;?

Como el título dice, ¿Cuál es la diferencia entre

char a[] = ?string?; and 
char *p = ?string?;  

Esta pregunta se la hicieron a mí en la entrevista.
Yo aun no entiendo la declaración.

char a[] = ?string?

Aquí lo que se ? operador? Es una parte de una cadena o tiene algún significado especial?

  • No se compila en MSVC…
  • Apuesta el entrevistador significaba » lugar de ?. El ? el símbolo se utiliza para el terciario operador, pero esta no es la sintaxis válida para ello.
  • Esto es probablemente un caso de mojibake. Esto no es C++.
  • Seguramente no compilador de C o C++ compilador.
  • return blah ? doFoo() : doOtherFoo(); es un ejemplo de el ? operador. Es funcionalmente equivalente a if (blah) return doFoo(); else return doOtherFoo();.
  • Es posible que la pregunta estaba usando el comienzo/fin de cotizaciones, y su fuente, por alguna razón, no podía encontrar, así que ellos prestados como ?s.
  • Mi conjetura: Código fue copiado en el MS Word, las cotizaciones fueron convertidos, y que de algún modo se convierte de nuevo. O hay una falta #define ? ". No sé si eso se compila, aunque.
  • difference-between-char-str-string-and-char-str-string
  • la pregunta fue modificada (signos de interrogación fueron reemplazados con doble comillas donde corresponda) para mejorar la visibilidad en Google y fue pedido expresamente a no rodar de nuevo. Por qué hiciste eso? Totalmente imprudente mover.
  • La pregunta había sido modificado hasta el punto de ser unintelligble! Tuve que leer la pregunta original para entender aún lo que se pide.
  • Específicamente, los signos de interrogación se parte de la OP de la cuestión, de modo que la eliminación de ellos hizo imposible entender lo que se le pide.

8 Kommentare

  1. 84

    La primera es la matriz de la otra es puntero.

    La declaración del array char a[6]; las solicitudes que el espacio de seis personajes que se destine a ser conocido por el nombre de a. Es decir, hay un lugar llamado a en la que seis personajes pueden sentarse. La declaración de puntero char *p; por otro lado, las solicitudes de un lugar que contiene un puntero. El puntero es ser conocido por el nombre de p, y puede apuntar a cualquier char (contiguos o array de caracteres) en cualquier lugar.

    Las declaraciones

     char a[] = "string";
     char *p = "string"; 

    podría resultar en estructuras de datos que se podría representar así:

         +---+---+---+---+---+---+----+
      a: | s | t | r | i | n | g | \0 |
         +---+---+---+---+---+---+----+
         +-----+     +---+---+---+---+---+---+---+ 
      p: |  *======> | s | t | r | i | n | g |\0 |    
         +-----+     +---+---+---+---+---+---+---+ 

    Es importante darse cuenta de que una referencia como x[3] genera código diferente dependiendo de si x es una matriz o un puntero. Dadas las declaraciones anteriores, cuando el compilador ve la expresión a[3], se emite un código para que se inicie en la ubicación a, mover tres elementos pasado, y recuperar el carácter de allí. Cuando ve la expresión p[3], se emite un código para que se inicie en la ubicación p, recuperar el valor del puntero de ahí, añadir tres tamaños de elemento con el puntero, y, finalmente, recuperar el carácter señalado. En el ejemplo anterior, tanto a[3] y p[3] pasar a ser el personaje l, pero el compilador llega de manera diferente.

    Fuente: comp.lang.c lista de preguntas frecuentes · Pregunta 6.2

    • Apuesto a que @Sachin considera que casos como el de const char *p = "string"; p = "another string"; printf("%c", p[3]); (Sí, char *p = "string"; será un error de compilación)
    • +1 para representar la asignación de memoria
  2. 91

    La ? parece ser un error tipográfico, no es semánticamente válido. Así que la respuesta asume la ? es un error tipográfico y explica lo que, probablemente, el entrevistador realmente quería preguntar.


    Ambos son muy diferentes, para empezar:

    1. El primero crea un puntero.
    2. En el segundo se crea una matriz.

    Leer en para una explicación más detallada:

    La Matriz versión:

    char a[] = "string";  

    Crea una matriz que es lo suficientemente grande para contener el literal de cadena «cadena», incluyendo su NULL terminator. La matriz string se inicializa con el literal de cadena «cadena». La matriz puede ser modificado en un momento posterior. También, la matriz del tamaño es conocido incluso en tiempo de compilación, por lo que sizeof operador se puede utilizar para determinar su tamaño.


    El puntero de la versión:

    char *p  = "string"; 

    Crea un puntero para señalar a un literal de cadena «cadena». Esto es más rápido que el de la matriz de versión, pero la cadena apuntada por el puntero no debe ser cambiado, ya que se encuentra en sólo lectura y aplicación definidos de la memoria. La modificación de un literal de cadena de resultados en un Comportamiento Indefinido.

    De hecho en C++03 infravalore[Ref 1] el uso de literales de cadena sin el const palabra clave. Así que la declaración debe ser:

    const char *p = "string";

    También,usted necesidad de utilizar el strlen() función, y no sizeof para encontrar el tamaño de la cadena desde el sizeof operador simplemente le dan el tamaño de la variable puntero.


    Que versión es mejor y cual debo usar?

    Depende del Uso.

    • Si usted no necesita hacer ningún cambio a la cadena, utilice el puntero de la versión.
    • Si desea cambiar los datos, el uso de la matriz de la versión.

    Nota: Esto no es un C++ pero esto es C específica.

    Tenga en cuenta que, el uso de literales de cadena sin el const palabra clave es perfectamente válido en C.
    Sin embargo, la modificación de un literal de cadena es todavía un Comportamiento Indefinido en C[Ref 2].

    Esto trae a colación una pregunta interesante,

    ¿Cuál es la diferencia entre char* y const char* cuando se utiliza con los literales de cadena en C?


    Para Standerdese Fans:

    [Ref 1]C++03 Estándar: §4.2/2

    Un literal de cadena (2.13.4) que no es una gran cadena literal puede ser convertido a un r-value de tipo «puntero a char»; una amplia literal de cadena puede ser convertido a un r-value de tipo «puntero a wchar_t». En cualquier caso, el resultado es un puntero al primer elemento de la matriz. Esta conversión se considera sólo cuando hay un explícito apropiado puntero de tipo de destino, y no cuando hay una necesidad general para convertir de un lvalue a un r-value. [Nota: esta conversión está en desuso. Ver Anexo D. ] Para el propósito de la clasificación en la resolución de sobrecarga (13.3.3.1.1), esta conversión se considera una matriz-a-puntero de conversión seguido por una calificación de conversión (4.4). [Ejemplo: «abc» se convierte en «puntero const char» como una matriz-a-puntero de la conversión, y luego a «puntero a char» como requisito de la conversión. ]

    C++11 simplemente elimina la anterior cita que implica que es ilegal el código en C++11.

    [Ref 2]estándar C99 6.4.5/5 «Literales de Cadena – Semántica»:

    En la traducción de la fase 7, un byte o un código de valor cero se anexa a cada secuencia de caracteres multibyte que los resultados de un literal de cadena o literales. Los juegos de caracteres multibyte secuencia es entonces utilizado para inicializar una matriz de almacenamiento estático duración y longitud suficiente para contener la secuencia. Para cadena de caracteres literales, los elementos de un array de tipo char, y se inicializan con los bytes individuales de la secuencia de caracteres multibyte; porque ancha literales de cadena, los elementos de la matriz tienen el tipo wchar_t, y se inicializan con la secuencia de caracteres anchos…

    Es indefinido si estas matrices son distintos siempre que sus elementos tienen los valores adecuados. Si el programa intenta modificar una matriz, el comportamiento es indefinido.

    • Cualquier razonamiento técnico para la downvote es muy apreciada.
    • +1 para mencionar sobre literal.
    • ¿Qué se entiende por «Esto es más rápido»?
    • No estoy de acuerdo con If you do not need to make any changes to the string, use the pointer version. – si usted no necesita hacer ningún cambio a la cadena, es probable que desee utilizar const char a[] = "string";, es decir, sólo añadir un const. Evita una reubicación cuando el enlazador dinámico hace su trabajo durante el inicio (en Linux, al menos). Consulte Cómo escribir bibliotecas compartidas sección 2.4.1 para una discusión más larga.
  3. 12
    char a[] = "string";

    Asigna la cadena en la pila.

    char *p = "string";

    Esto crea un puntero a la pila que señala el literal en el segmento de datos del proceso.

    ? es el que lo escribió no saber lo que estaban haciendo.

    • Yo también lo creo así. A esto debe agregarse erróneamente.. de todos Modos gracias por la respuesta..
    • Dado que la pregunta está pidiendo detalles sobre algo trivial, creo que la respuesta debe explorar las posibilidades en más profundidad. Específicamente, «char a[]… asigna…en la pila» supone que dentro de una función y no global, y además se refiere a la a[] mientras no mencionar que dentro de una función, de hecho, hay una copia en tiempo de ejecución de todo el texto de la constante segmento de datos en la pila. char* uso que crea unaconst puntero de la pila o como un mundial en el segmento de datos – y la inicializa en tiempo de ejecución o (probablemente) tiempo de compilación, respectivamente, a la dirección de la const texto.
    • Esta respuesta es errónea. El 2º fragmento de código crea un error de compilación 😛
    • De hecho lo es.Para declarar un puntero a cadena literal sin const calificador está en desuso en C++03, por Lo que el segundo fragmento no es legal el código de C++.
    • Se compila con algunos compiladores (por ejemplo de Microsoft Visual C++ 2010), por lo que cuando se dice que crea error de compilación, debe ser más específico – escribir la versión del compilador, o (como se menciona en otra respuesta) que esto es contra el estándar de c++ (C++03 C++11).
  4. 7

    Pila, montón, datasegment(y SEV) y el texto segmento son los cuatro segmentos de memoria del proceso. Todas las variables locales definidas estará en la pila. Dynmically la memoria asignada utilizando malloc y calloc será en el montón. Todos los mundiales y las variables estáticas será en el segmento de datos. Segmento de texto tendrá el código ensamblador del programa y algunas constantes.

    En estos 4 segements, segmento de texto es el READ ONLY segmento y en el de todos los otros tres es para READ y WRITE.

    char a[] = "string"; – Este statemnt va a asignar memoria para 7 bytes en la pila(porque variable local) y se mantendrán todos los 6 caracteres(s, t, r, i, n, g) más el carácter NULL (\0) en la final.

    char *p = "string"; – Esta declaración ha de asignar memoria para 4 bytes(si es de 32 bits de la máquina) en la pila(porque esto también es una variable local) y se llevará a cabo el puntero de la cadena constante cuyo valor es "string". Este 6 bytes de la cadena constante, que será en el segmento de texto. Este es un valor constante. Variable de puntero p sólo apunta a esa cadena.

    Ahora a[0] (índice puede ser de 0 a 5) significa, tendrá acceso a primer carácter de la cadena que está en la pila. Por lo que podemos escribir también en esta posición. a[0] = 'x'. Esta operación está permitido porque hemos READ WRITE de acceso en la pila.

    Pero p[0] = 'x' le lleva a chocar, porque sólo tenemos READ acceso a texto segmento. Un fallo de segmentación sucederá si hacemos cualquier escritura en el segmento de texto.

    Pero usted puede cambiar el valor de la variable p, debido a su variable local en la pila. como a continuación

    char *p = "string";
    printf("%s", p);
    p = "start";
    printf("%s", p);

    Esto está permitido. Aquí estamos cambiando la dirección almacenada en el puntero variable p a la dirección de la cadena start(de nuevo start también es de sólo lectura de los datos en texto segmento). Si desea modificar los valores presentes en *p significa ir para la asignación dinámica de memoria.

    char *p = NULL;
    p = malloc(sizeof(char)*7);
    strcpy(p, "string");

    Ahora p[0] = 'x' se permite la operación, porque ahora estamos escribiendo en el montón.

    • gran explicación, lo único que no estoy seguro, será literal de cadena ser almacenados en el segmento de texto o en el segmento de datos?
    • Los literales de cadena son de sólo lectura de los datos, por lo que la mayoría de los compiladores utilizan para stor es en el segmento de texto.
    • Así, los bytes de la cadena de literales son almacenados en el segmento de texto, y esto es cierto para cada compilador de C?, y para C++?
  5. 6

    char *p = "string"; crea un puntero a la memoria de sólo lectura donde literal de cadena "string" se almacena. Tratando de modificar la cadena que p puntos que conduce a un comportamiento indefinido.

    char a[] = "string"; crea una matriz e inicializa su contenido mediante el uso de literales de cadena "string".

  6. 3

    Difieren con respecto a donde se almacena la memoria. Lo ideal es que el segundo debe utilizar const char *.

    La primera

    char buf[] = "hello";

    crea un sistema automático de buffer lo suficientemente grande como para contener los caracteres y de las copias de ellos (incluyendo el terminador nulo).

    El segundo

    const char * buf = "hello";

    debe utilizar const y simplemente crea un puntero que apunta a la memoria almacena generalmente en estático espacio donde es ilegal modificar.

    Lo contrario (de hecho, usted puede modificar la primera de forma segura y no la segunda) es que es seguro regresar el segundo puntero de una función, pero no la primera. Esto es debido a que el segundo seguirá siendo válido puntero de memoria fuera del alcance de la función, de la primera no.

    const char * sayHello()
    {
         const char * buf = "hello";
         return buf; //valid
    }
    
    const char * sayHelloBroken()
    {
         char buf[] = "hello";
         return buf; //invalid
    }
  7. 1

    a declara una matriz de char valores — una matriz de chars que se termina.

    p declara un puntero, que se refiere a una inmutable, terminado, C de la cadena, cuya exacta ubicación de almacenamiento es de aplicación definido. Tenga en cuenta que este debe ser constcalificado (por ejemplo,const char *p = "string";).

    Si que se imprima utilizando std::cout << "a: " << sizeof(a) << "\np: " << sizeof(p) << std::endl;, podrás ver las diferencias en sus tamaños (nota: los valores pueden variar según el sistema):

    a: 7
    p: 8

    Aquí ¿qué es ? operador? Es una parte de una cadena o tiene algún significado especial?

    char a[] = ?string?

    Supongo que una vez fueron comillas dobles "string", que potencialmente se convierten a «comillas tipográficas», entonces no podría ser representada como tal a lo largo del camino, y fueron convertidos a ?.

    • Sólo en raras ocasiones (por ejemplo, cuando usted debe mutar el char buffer).
    • Si usted no necesita mutar el char buffer, entonces debe ser una [static] const char a[] = "xyz";, no const char* p = "xyz"; ni const char* const p = "xyz"; – lo anterior implica p puede ser movido a un punto en otro lugar y si esa no es la intención, entonces es mejor no permitir la posibilidad, y tanto pedir el compilador de espacio tanto para el puntero de texto y en mi humilde opinión – sólo muestra una falta de precisión de los modelos mentales de lo que se le pide al compilador y desechos de espacio y tiempo en un unoptimised construir.
    • Yo no tengo ninguna intención o interés en ser insultante. Usted dice que yo estoy equivocado en muchos contextos – yo solo se habló de la «no necesidad de mutar contexto», así que por favor explique los muchos escenarios en los que estoy equivocado, y cómo [static] const char[] resultados en «desperdicio de espacio y tiempo».
    • FYI glandium.org/blog/?p=2361
  8. 0

    C y C++ son muy similares Puntero a Matriz de relaciones…

    No puedo hablar por el exacto ubicaciones de la memoria de las dos instrucciones que están pidiendo, pero me encontré que artículos interesantes y útiles para la comprensión de algunas de las diferencias entre el char declaración de Puntero, y una Matriz de char declaración.

    Para mayor claridad:

    C Puntero y Matriz de relación

    C++ Puntero a una Matriz

    Creo que es importante recordar que una matriz en C y C++, es un puntero constante para el primer elemento de la matriz. Y, en consecuencia, puede realizar aritmética de punteros en la matriz.

    char *p = «cadena»; <— Este es un puntero que apunta a la primera dirección de una cadena de caracteres.

    el siguiente también es posible:

    char *p;
    char a[] = "string";
    
    p = a; 

    En este punto p ahora hace referencia a la primera dirección de memoria de una (la dirección del primer elemento)

    y así *p == ‘s’

    *(p++) == ‘t’, y así sucesivamente. (o *(p+1) == ‘t’)

    y lo mismo trabajar para un: *(a++) o *(a+1) también igual a ‘t’

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea