Inicialización de la matriz de caracteres C: ¿qué sucede si hay menos caracteres en el literal de cadena que el tamaño de la matriz?

7 minutos de lectura

Avatar de usuario de lkkeepmoving
sigue moviéndote

No estoy seguro de qué habrá en la matriz de caracteres después de la inicialización de las siguientes maneras.

1.char buf[10] = "";

2. char buf[10] = " ";

3. char buf[10] = "a";

Para el caso 2, creo buf[0] debiera ser ' ', buf[1] debiera ser '\0'y de buf[2] a buf[9] será contenido aleatorio. Para el caso 3, creo buf[0] debiera ser 'a', buf[1] debe ser ‘\0’, y de buf[2] a buf[9] será contenido aleatorio.

¿Es eso correcto?

Y para el caso 1, ¿cuál será en el buf? buf[0] == '\0' y de buf[1] a buf[9] será contenido aleatorio?

  • Bueno, mi compilador no acepta su código (corregido): “tipo de matriz ‘char [10]’ no es asignable”.

    – Martín R.

    08/09/2013 a las 22:00

  • @MartinR ahora funcionará …

    – sigue moviéndote

    08/09/2013 a las 22:05

  • @lkkeepmoving: char buf[10]; buf = "a"; lo hace no compilar. – Inténtalo primero y luego copia/pega tu actual código en la pregunta. Eso ahorra mucho trabajo para usted y para todos los lectores de su pregunta.

    – Martín R.

    08/09/2013 a las 22:08

  • @MartinR Lo siento por eso. Pensé que puedo asignar el buf[] esto último pero parece que no. Ahora el código se ejecuta.

    – sigue moviéndote

    8 sep 2013 a las 22:14

  • Posible duplicado de ¿Cuenta un literal de cadena como inicializador parcial e inicialización cero?

    – Antti Haapala — Слава Україні

    5 de julio de 2016 a las 11:08

avatar de usuario de ouah
ouah

Esta no es la forma de inicializar una matriz, sino para:

  1. La primera declaración:

    char buf[10] = "";
    

    es equivalente a

    char buf[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
  2. La segunda declaración:

    char buf[10] = " ";
    

    es equivalente a

    char buf[10] = {' ', 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
  3. La tercera declaración:

    char buf[10] = "a";
    

    es equivalente a

    char buf[10] = {'a', 0, 0, 0, 0, 0, 0, 0, 0, 0};
    

Como puede ver, no hay contenido aleatorio: si hay menos inicializadores, el resto de la matriz se inicializa con 0. Este es el caso incluso si la matriz se declara dentro de una función.

  • Por el bien de la persona que hace la pregunta, vale la pena señalar que el estándar C requiere que cualquier inicialización de matriz parcialmente completa se rellene con cero para los elementos restantes (por el compilador). Esto se aplica a todos los tipos de datos, no solo char.

    – arroz

    08/09/2013 a las 21:54


  • @ouah por qué no hay ‘\0’ al final de buf[]?

    – sigue moviéndote

    8 sep 2013 a las 22:06

  • @lkkeepmoving 0 y '\0 tener el mismo valor.

    – ouah

    08/09/2013 a las 22:15

  • @Pacerier char buff[3] = "abcdefghijkl"; no es válido. char p3[5] = "String"; también es inválido. char p[6] = "String"; es válido y es lo mismo que char p[6] = {'S', 't', 'r', 'i', 'n', 'g'};.

    – ouah

    19 de diciembre de 2014 a las 11:17

  • @delive ¿Qué quiere decir y qué relevancia tuvo para esta respuesta?

    – subrayado_d

    31 de octubre de 2017 a las 9:24


  1. Estos son equivalentes

    char buf[10] = "";
    char buf[10] = {0};
    char buf[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
  2. Estos son equivalentes

    char buf[10] = " ";
    char buf[10] = {' '};
    char buf[10] = {' ', 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
  3. Estos son equivalentes

    char buf[10] = "a";
    char buf[10] = {'a'};
    char buf[10] = {'a', 0, 0, 0, 0, 0, 0, 0, 0, 0};
    

avatar de usuario de verbose
verboso

Editar: OP (o un editor) cambió silenciosamente algunas de las comillas simples en la pregunta original a comillas dobles en algún momento después de que proporcioné esta respuesta.

Su código dará como resultado errores del compilador. Su primer fragmento de código:

char buf[10] ; buf=""

es doblemente ilegal. Primero, en C, no existe tal cosa como un vacío char. Puede usar comillas dobles para designar una cadena vacía, como con:

char* buf = ""; 

Eso le dará un puntero a un NUL cadena, es decir, una cadena de un solo carácter con sólo el NUL personaje en ella. Pero no puede usar comillas simples sin nada dentro de ellas, eso no está definido. Si necesita designar el NUL carácter, tienes que especificarlo:

char buf="\0";

La barra invertida es necesaria para eliminar la ambigüedad del carácter '0'.

char buf = 0;

logra lo mismo, pero creo que el primero es un poco menos ambiguo de leer.

En segundo lugar, no puede inicializar matrices después de que se hayan definido.

char buf[10];

declara y define la matriz. El identificador de matriz buf ahora es una dirección en la memoria, y no puede cambiar dónde buf puntos a través de la asignación. Asi que

buf =     // anything on RHS

es ilegal. Su segundo y tercer fragmento de código son ilegales por este motivo.

Para inicializar una matriz, debe hacerlo en el momento de la definición:

char buf [10] = ' ';

le dará una matriz de 10 caracteres, siendo el primer carácter el espacio '\040' y el resto siendo NULes decir, '\0'. Cuando se declara y define una matriz con un inicializador, los elementos de la matriz (si los hay) más allá de los que tienen valores iniciales especificados se rellenan automáticamente con 0. No habrá ningún “contenido aleatorio”.

Si declara y define la matriz pero no la inicializa, como se muestra a continuación:

char buf [10];

tendrás contenido aleatorio en todos los elementos.

  • “Para inicializar una matriz, debe hacerlo en el momento de la definición …” Esto y la siguiente línea lo hacen mejor que la respuesta aceptada.

    –Laurie Stearn

    28 de diciembre de 2016 a las 3:48


La parte relevante del borrador estándar C11 n1570 6.7.9 inicialización dice:

14 Una matriz de tipo de carácter puede inicializarse mediante un literal de cadena de caracteres o un literal de cadena UTF-8, opcionalmente encerrado entre llaves. Los bytes sucesivos del literal de cadena (incluido el carácter nulo de terminación si hay espacio o si la matriz tiene un tamaño desconocido) inicializan los elementos de la matriz.

y

21 Si hay menos inicializadores en una lista entre llaves que elementos o miembros de un agregado, o menos caracteres en un literal de cadena utilizado para inicializar una matriz de tamaño conocido que elementos en la matriz, el resto del agregado se inicializará implícitamente al igual que los objetos que tienen duración del almacenamiento estático.

Por lo tanto, se agrega el ‘\0’, si hay suficiente espacioy los caracteres restantes se inicializan con el valor que un static char c; se inicializaría dentro de una función.

Finalmente,

10 Si un objeto que tiene duración de almacenamiento automático no se inicializa explícitamente, su valor es indeterminado. Si un objeto que tiene estático o la duración del almacenamiento del subproceso no se inicializa explícitamente, entonces:

[–]

  • si es de tipo aritmético, se inicializa a cero (positivo o sin signo);

[–]

Por lo tanto, char al ser un tipo aritmético, también se garantiza que el resto de la matriz se inicialice con ceros.

Curiosamente, es posible inicializar arreglos de cualquier forma y en cualquier momento del programa, siempre que sean miembros de un struct o union.

Programa de ejemplo:

#include <stdio.h>

struct ccont
{
  char array[32];
};

struct icont
{
  int array[32];
};

int main()
{
  int  cnt;
  char carray[32] = { 'A', 66, 6*11+1 };    // 'A', 'B', 'C', '\0', '\0', ...
  int  iarray[32] = { 67, 42, 25 };

  struct ccont cc = { 0 };
  struct icont ic = { 0 };

  /*  these don't work
  carray = { [0]=1 };           // expected expression before '{' token
  carray = { [0 ... 31]=1 };    // (likewise)
  carray = (char[32]){ [0]=3 }; // incompatible types when assigning to type 'char[32]' from type 'char *'
  iarray = (int[32]){ 1 };      // (likewise, but s/char/int/g)
  */

  // but these perfectly work...
  cc = (struct ccont){ .array='a' };        // 'a', '\0', '\0', '\0', ...
  // the following is a gcc extension, 
  cc = (struct ccont){ .array={ [0 ... 2]='a' } };  // 'a', 'a', 'a', '\0', '\0', ...
  ic = (struct icont){ .array={ 42,67 } };      // 42, 67, 0, 0, 0, ...
  // index ranges can overlap, the latter override the former
  // (no compiler warning with -Wall -Wextra)
  ic = (struct icont){ .array={ [0 ... 1]=42, [1 ... 2]=67 } }; // 42, 67, 67, 0, 0, ...

  for (cnt=0; cnt<5; cnt++)
    printf("%2d %c %2d %c\n",iarray[cnt], carray[cnt],ic.array[cnt],cc.array[cnt]);

  return 0;
}

Avatar de usuario de Erric Rapsing
Erric rapeando

No estoy seguro, pero normalmente inicializo una matriz en “” en ese caso, no necesito preocuparme por el final nulo de la cadena.

main() {
    void something(char[]);
    char s[100] = "";

    something(s);
    printf("%s", s);
}

void something(char s[]) {
    // ... do something, pass the output to s
    // no need to add s[i] = '\0'; because all unused slot is already set to '\0'
}

¿Ha sido útil esta solución?