Inicjalizacja tablicy znaków C

Nie jestem pewien, co będzie w tablicy znaków po inicjalizacji w następujący sposób.

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

Dla Przypadku 2, myślę buf[0] powinny być ' ', buf[1] powinno być '\0', a od buf[2] do buf[9] będzie losową treścią. Dla przypadku 3, myślę, że buf[0] powinno być 'a', buf[1] powinno być "\0", a od buf[2] do buf[9] będzie losową treścią.

Czy to prawda?

I w przypadku 1, co będzie w buf? buf[0] == '\0' i od buf[1] do buf[9] będzie losowa treść?

Author: Chris Krycho, 2013-09-08

6 answers

Nie tak inicjalizujesz tablicę, ale dla:

  1. Pierwsza deklaracja:

    char buf[10] = "";
    

    Jest równoważne

    char buf[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
  2. Druga deklaracja:

    char buf[10] = " ";
    

    Jest równoważne

    char buf[10] = {' ', 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
  3. Trzecia deklaracja:

    char buf[10] = "a";
    

    Jest równoważne

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

Jak widać, brak losowej zawartości: jeśli jest mniej inicjalizatorów, pozostała część tablicy jest inicjalizowana przez 0. Tak jest nawet jeśli tablica jest deklarowana wewnątrz funkcji.

 230
Author: ouah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-20 18:53:49
  1. Są to równoważne

    char buf[10] = "";
    char buf[10] = {0};
    char buf[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
  2. Są to równoważne

    char buf[10] = " ";
    char buf[10] = {' '};
    char buf[10] = {' ', 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
  3. Są to równoważne

    char buf[10] = "a";
    char buf[10] = {'a'};
    char buf[10] = {'a', 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
 28
Author: Steven Penny,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-29 16:15:36

Edit: OP (lub edytor) po cichu zmienił niektóre pojedyncze cytaty w oryginalnym Pytaniu na podwójne cytaty w pewnym momencie po tym, jak podałem tę odpowiedź.

Twój kod spowoduje błędy kompilatora. Twój pierwszy fragment kodu:

char buf[10] ; buf = ''
Jest podwójnie nielegalne. Po pierwsze, w C nie ma czegoś takiego jak pusty char. Możesz użyć podwójnych cudzysłowów, aby wyznaczyć pusty łańcuch, tak jak w przypadku:
char* buf = ""; 

, który da ci wskaźnik do NUL ciągu, czyli jednoznakowy ciąg znaków zawierający tylko znak NUL. Ale nie można używać pojedynczych cudzysłowów z niczym wewnątrz nich-to jest nieokreślone. Jeśli chcesz wyznaczyć znak NUL, musisz go określić:

char buf = '\0';

Odwrotny ukośnik jest konieczny do odróżnienia od znaku '0'.

char buf = 0;

Osiąga to samo, ale to pierwsze jest trochę mniej niejednoznaczne do odczytania, myślę.

Po drugie, nie można inicjalizować tablic po ich zdefiniowaniu.

char buf[10];

Deklaruje i definiuje tablicę. Identyfikator tablicy buf jest teraz adresem w pamięci i nie można zmienić miejsca, w którym buf wskazuje przez przypisanie. Więc

buf =     // anything on RHS
Jest nielegalne. Twój drugi i trzeci fragment kodu jest z tego powodu nielegalny.

Aby zainicjować tablicę, musisz to zrobić w momencie definicji:

char buf [10] = ' ';

Da ci tablicę 10 znaków, z pierwszym znakiem jest spacja '\040', a reszta NUL, tzn. '\0'. Kiedy tablica jest zadeklarowana i zdefiniowana za pomocą inicjalizatora, elementy tablicy (jeśli istnieją) poza tymi z podanymi wartościami początkowymi są automatycznie wypełniane za pomocą 0. Nie będzie żadnych "losowych treści".

Jeśli zadeklarujesz i zdefiniujesz tablicę, ale jej nie zainicjalizujesz, jak w poniższym przykładzie:

char buf [10];

Będziesz miał losową zawartość we wszystkich elementach.

 28
Author: verbose,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-10 08:50:50

Odpowiednia część projektu standardu C11 n1570 6.7.9 inicjalizacja mówi:

14 tablica typu znakowego może być zainicjalizowana ciągiem znaków literal lub UTF-8 dosłowne, opcjonalnie zamknięte w szelkach. Kolejnych bajtów ciągu znaków (w tym kończący znak null, jeśli jest miejsce lub jeśli tablica jest nieznanego rozmiaru) zainicjalizuj elementy tablicy.

I

21 Jeśli na liście zamkniętej nawiasami jest mniej inicjalizatorów niż elementów lub członków z agregatu lub mniej znaków w łańcuchu znaków używanych do inicjalizacji tablicy znanych wielkość niż w tablicy są elementy, reszta agregatu powinna być inicjalizowane domyślnie tak samo jak obiekty, które mają statyczny czas przechowywania .

W ten sposób dodaje się "\0", jeśli jest wystarczająco dużo miejsca , a pozostałe znaki są inicjalizowane wartością static char c;, która zostanie zainicjowana w funkcji.

Wreszcie,

10 jeśli obiekt z automatycznym czasem przechowywania nie jest jawnie inicjowany, jego wartość wynosi nieokreślony. Jeśli obiekt, który ma statyczny lub czas przechowywania wątku nie jest zainicjowany jawnie, wtedy:

[--]

  • jeśli ma typ arytmetyczny, jest inicjalizowany na (dodatni lub niepodpisany) zero;

[--]

Tak więc, char jako typ arytmetyczny, reszta tablicy jest również zainicjalizowana zerami.

 9
Author: Antti Haapala,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-05 11:03:47

Co ciekawe, możliwe jest inicjowanie tablic w dowolny sposób w dowolnym momencie w programie, pod warunkiem, że są członkami struct lub union.

Przykładowy program:

#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;
}
 3
Author: user3381726,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-13 10:51:07

Nie jestem pewien, ale zwykle inicjalizuję tablicę do "" w takim razie nie muszę się martwić o zerowy koniec łańcucha.

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'
}
 1
Author: Erric Rapsing,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-01 01:41:58