C 문자 배열 초기화


119

다음과 같은 방법으로 초기화 후 char 배열에 무엇이 있을지 잘 모르겠습니다.

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

경우 2, 나는 생각 buf[0]해야한다 ' ', buf[1]해야한다 '\0', 그리고에서 buf[2]buf[9]임의의 콘텐츠 될 것입니다. 케이스 3의 경우 , 이어야하고 , '\ 0' buf[0]이어야하며 'a', to 는 임의의 콘텐츠가 될 것입니다.buf[1]buf[2]buf[9]

그 맞습니까?

그리고 사례 1의 경우 buf? buf[0] == '\0'과에서 buf[1]하는 것은 buf[9]임의의 콘텐츠 것인가?


2
글쎄요, 제 컴파일러는 당신의 (수정 된) 코드를 받아들이지 않습니다 : "array type 'char [10]'is not assignable".
Martin R

@MartinR 지금은 ... 작동합니다
lkkeepmoving

1
@lkkeepmoving : 컴파일 char buf[10]; buf = "a";하지 않습니다 . -먼저 시도한 다음 실제 코드를 복사 하여 질문에 붙여 넣으십시오 . 이는 귀하와 귀하의 질문에 대한 모든 독자를 위해 많은 작업을 절약합니다.
Martin R

@MartinR 죄송합니다. 후자에 buf []를 할당 할 수 있다고 생각했지만 그렇지 않은 것 같습니다. 이제 코드가 실행됩니다.
lkkeepmoving

답변:


222

이것은 배열을 초기화하는 방법이 아니라 다음을위한 것입니다.

  1. 첫 번째 선언 :

    char buf[10] = "";

    다음과 같다

    char buf[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  2. 두 번째 선언 :

    char buf[10] = " ";

    다음과 같다

    char buf[10] = {' ', 0, 0, 0, 0, 0, 0, 0, 0, 0};
  3. 세 번째 선언 :

    char buf[10] = "a";

    다음과 같다

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

보시다시피 임의의 콘텐츠가 없습니다. 초기화 프로그램이 더 적 으면 나머지 배열은 0. 이것은 배열이 함수 내에서 선언 된 경우에도 마찬가지입니다.


46
질문을하는 사람을 위해, C 표준은 (컴파일러에 의해) 나머지 요소에 대해 부분적으로 완료된 배열 초기화를 0으로 채워야한다는 점을 지적 할 가치가 있습니다. 이는 .NET뿐만 아니라 모든 데이터 유형에 적용 char됩니다.
paddy

4
@ouah 왜 buf [] 끝에 '\ 0'이 없나요?
lkkeepmoving

14
@lkkeepmoving 0'\0동일한 값을 갖습니다.
ouah

1
@lkkeepmoving 초기화와 할당은 두 가지 다른 짐승이므로 C를 사용하면 char 배열의 이니셜 라이저로 문자열을 제공 할 수 있지만 배열 할당은 금지됩니다 (ouah가 말했듯이).
Lorenzo Donati-Codidact.com 2013 년

3
@Pacerier char buff[3] = "abcdefghijkl";가 잘못되었습니다. char p3[5] = "String";또한 유효하지 않습니다. char p[6] = "String";은 유효하며과 동일합니다 char p[6] = {'S', 't', 'r', 'i', 'n', 'g'};.
ouah

28

편집 : OP (또는 편집자)는이 답변을 제공 한 후 원래 질문의 일부 작은 따옴표를 큰 따옴표로 자동 변경했습니다.

코드로 인해 컴파일러 오류가 발생합니다. 첫 번째 코드 조각 :

char buf[10] ; buf = ''

이중 불법입니다. 첫째, C에는 비어있는 char. 다음과 같이 큰 따옴표를 사용하여 빈 문자열을 지정할 수 있습니다.

char* buf = ""; 

그러면 NUL문자열에 대한 포인터가 제공됩니다 . 즉, 문자 만있는 단일 문자열입니다 NUL. 그러나 그 안에 아무것도없는 작은 따옴표는 사용할 수 없습니다. 즉, 정의되지 않았습니다. NUL문자 를 지정해야하는 경우 지정해야합니다.

char buf = '\0';

백 슬래시는 문자와 구별하기 위해 필요합니다 '0'.

char buf = 0;

똑같은 일을 해내지만, 전자는 좀 덜 애매 모호하다고 생각합니다.

둘째, 배열을 정의한 후에는 초기화 할 수 없습니다.

char buf[10];

배열을 선언하고 정의합니다. 배열 식별자 buf는 이제 메모리의 주소이며 buf할당을 통해 포인트 위치를 변경할 수 없습니다 . 그래서

buf =     // anything on RHS

불법입니다. 두 번째 및 세 번째 코드 조각은 이러한 이유로 불법입니다.

배열을 초기화하려면 정의 할 때 수행해야합니다.

char buf [10] = ' ';

첫 번째 문자는 공백 '\040'이고 나머지는 NUL, 즉 '\0'. 이니셜 라이저를 사용하여 배열을 선언하고 정의하면 지정된 초기 값이있는 배열 요소 (있는 경우)를 지나는 배열 요소가 자동으로 0. "무작위 콘텐츠"는 없습니다.

다음과 같이 배열을 선언하고 정의하지만 초기화하지 않는 경우 :

char buf [10];

모든 요소에 무작위 콘텐츠가 있습니다.


"배열을 초기화하려면 정의 할 때 수행해야합니다 ..."이것과 다음 줄은 허용되는 대답보다 더 잘 만듭니다.
로리 Stearn

26
  1. 이들은 동등합니다

    char buf[10] = "";
    char buf[10] = {0};
    char buf[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  2. 이들은 동등합니다

    char buf[10] = " ";
    char buf[10] = {' '};
    char buf[10] = {' ', 0, 0, 0, 0, 0, 0, 0, 0, 0};
  3. 이들은 동등합니다

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

8

C11 표준 초안 n1570 6.7.9 초기화의 관련 부분은 다음과 같습니다.

14 문자 유형의 배열은 문자열 리터럴 또는 UTF-8 문자열 리터럴로 초기화 될 수 있으며 선택적으로 중괄호로 묶입니다. 문자열 리터럴의 연속 바이트 (공간이 있거나 배열 크기를 알 수없는 경우 종료 널 문자 포함)는 배열의 요소를 초기화합니다.

(21) 이있는 경우 요소 또는 집합의 구성원, 또는이보다 중괄호로 둘러싸인 목록에 적은 이니셜 배열의 요소가보다 알려진 크기의 배열을 초기화하는 데 사용되는 문자열 리터럴 적은 문자, 집합의 나머지 정적 저장 기간 이있는 객체와 동일하게 암시 적으로 초기화 됩니다.

따라서 공간이 충분 하면 '\ 0'이 추가 되고 나머지 문자는 static char c;함수 내에서 a가 초기화되는 값 으로 초기화됩니다.

드디어,

10 자동 저장 기간이있는 개체가 명시 적으로 초기화되지 않은 경우 해당 값은 확정되지 않습니다. 정적 또는 스레드 저장 기간이 있는 객체가 명시 적으로 초기화되지 않은 경우 :

[-]

  • 산술 유형이 있으면 0 (양수 또는 부호 없음)으로 초기화됩니다.

[-]

따라서 char산술 유형이기 때문에 배열의 나머지 부분도 0으로 초기화됩니다.


3

흥미롭게도 배열이 a struct또는의 멤버 인 경우 프로그램에서 언제든지 어떤 방식 으로든 배열을 초기화 할 수 있습니다 union.

예제 프로그램 :

#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;
}

1

확실하지 않지만 일반적으로 배열을 ""로 초기화합니다.이 경우 문자열의 null 끝에 대해 ​​걱정할 필요가 없습니다.

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'
}

암시 적 int 규칙을 실제로 사용해서는 안됩니다 . 당신의 유형을 지정해야합니다 main()(그리고 당신은 또한 사용해야 void즉, int main(void) { ... }이 코드는 나중에 C99에 대한 컴파일되지 않도록. C99이 규칙을 제거있어. 여기에서 주목해야 할 또 다른 일이 있다는 것입니다 시작 C99와 함께, 당신은 생략하는 경우 return에 메인은 자동으로이 return 0;전과 암시 / 배치 }의 주요 끝에서 당신은 C99 전에 작동 암시 INT 규칙을 사용하고있다, 그러나 당신이 암시를 사용하고있다. return즉, 단지 C99와 함께 작동 이상을 , 두 분명히 모순 .
RastaJedi
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.