programing

char 배열이 null로 종료되는 것이 보증됩니까?

sourcejob 2022. 9. 29. 00:15
반응형

char 배열이 null로 종료되는 것이 보증됩니까?

#include <stdio.h>

int main() {
    char a = 5;
    char b[2] = "hi"; // No explicit room for `\0`.
    char c = 6;

    return 0;
}

큰따옴표로 둘러싸인 문자열을 쓸 때마다 C는 자동으로 해당 문자열을 포함하는 문자 배열을 만듭니다.이 문자열은 \0 문자 http://www.eskimo.com/ ~scs/cclass/notes/sx8.gl로 끝납니다.

위의 예에서는b컴파일러는 메모리 스토어 명령어를 재구성하고 있기 때문에, 2 문자 밖에 사용할 수 없습니다.a그리고.c이 저장되기 전에b을 위한 공간을 마련하기 위해 기억으로\0어레이의 끝에 있습니다.

이것은 예상된 것입니까, 아니면 정의되지 않은 동작에 도달한 것입니까?

를 초기화할 수 있습니다.char배열이 null 터미네이터 이외의 문자열 의 모든 문자를 포함할 수 있을 정도로 충분히 큰 경우 문자열이 포함된 배열입니다.

이는 C 표준의 섹션 6.7.9p14에 자세히 설명되어 있습니다.

문자열 리터럴 또는 UTF-8 문자열 리터럴에 의해 문자 유형의 배열을 초기화할 수 있습니다(옵션으로 중괄호로 묶음).문자열 리터럴의 연속 바이트(공간이 있거나 배열 크기를 알 수 없는 경우 끝의 늘 문자 포함)에 따라 배열 요소가 초기화됩니다.

그러나 어레이는 null로 종료되지 않으므로 문자열로 처리할 수 없습니다.따라서 기술된 대로 스트링 조작을 실행하고 있지 않기 때문에b, 당신의 코드는 정상입니다.

너무 긴 문자열로 초기화할 수 없습니다.

char b[2] = "hello";

이는 배열에 들어갈 수 있는 것보다 많은 이니셜라이저를 제공하므로 제약조건 위반이 됩니다.섹션 6.7.9p2는 이를 다음과 같이 기술한다.

이니셜라이저는 초기화 대상 엔티티에 포함되지 않은 객체의 값을 제공하려고 시도해서는 안 됩니다.

어레이를 다음과 같이 선언하고 초기화할 경우:

char b[] = "hi"; 

그리고나서b크기 3의 배열이 됩니다.이 배열은 문자열 내의 2개의 문자와 끝의 늘바이트를 일정하게 유지할 수 있을 정도로 충분히 크며,b

요약:

어레이의 크기가 고정되어 있는 경우:

  • 초기화에 사용된 문자열 상수가 배열보다 짧으면 배열에 문자열 문자가 포함되어 연속 요소가 0으로 설정되므로 배열에 문자열이 포함됩니다.
  • 배열이 문자열 요소를 포함할 수 있을 정도로 충분히 크지만 늘 터미네이터가 포함되지 않은 경우 배열은 늘 터미네이터가 없는 문자열에 문자를 포함합니다.즉, 어레이는 문자열이 아닙니다.
  • 문자열 상수(null 터미네이터를 카운트하지 않음)가 어레이보다 길 경우 정의되지 않은 동작을 트리거하는 제약 조건 위반입니다.

어레이에 명시적 크기가 없는 경우 문자열에 끝의 늘바이트를 더한 값을 유지하도록 어레이의 크기가 조정됩니다.

큰따옴표로 둘러싸인 문자열을 쓸 때마다 C는 자동으로 문자열 배열을 작성합니다.이 문자열은 \0자로 끝납니다.

그 메모들은 이 경우에 약간 오해의 소지가 있다.업데이트해야 할 것 같습니다.

이런 걸 쓸 때

char *p = "Hello";

또는

printf("world!\n");

C는 자동으로 적절한 크기의 문자열 배열을 만듭니다.이 배열에는 문자열이 포함됩니다.\0성격.

다만, 어레이 이니셜라이저의 경우는, 약간 다릅니다.글을 쓸 때

char b[2] = "hi";

문자열은 작성하는 배열의 이니셜라이저일 뿐입니다.크기를 완전히 제어할 수 있습니다.몇 가지 가능성이 있습니다.

char b0[] = "hi";     // compiler infers size
char b1[1] = "hi";    // error
char b2[2] = "hi";    // No terminating 0 in the array. (Illegal in C++, BTW)
char b3[3] = "hi";    // explicit size matches string literal
char b4[10] = "hi";   // space past end of initializer is always zero-initialized

위해서b0사이즈를 지정하지 않기 때문에 컴파일러는 문자열 이니셜라이저를 사용하여 적절한 사이즈(3)를 선택합니다.

위해서b1크기를 지정했는데 크기가 너무 작아서 컴파일러에 오류가 나타납니다.

위해서b2문의하신 경우입니다만, 스트링 이니셜라이저의 명시적인 문자에 겨우 들어갈 정도의 사이즈를 지정합니다만, 끝은 지정할 수 없습니다.\0이것은 특별한 경우입니다.합법적이긴 하지만 결국엔...b2는 적절한 늘 종단 문자열이 아닙니다.기껏해야 드물기 때문에 컴파일러가 경고를 줄 수 있습니다.이 케이스에 대한 자세한 내용은 이 질문을 참조하십시오.

위해서b3적절한 크기를 지정하면 다음과 같이 정확한 크기의 어레이에서 적절한 문자열을 얻을 수 있습니다.b0.

위해서b4사이즈가 너무 큰 것을 지정했습니다만, 이것은 문제가 되지 않습니다.어레이에 끝부분을 넘는 여분의 공간이 있습니다.\0(사실, 이 여분의 공간도 다음 주소로 채워질 것입니다.\0.) 이 추가 공간을 통해 다음과 같은 작업을 안전하게 수행할 수 있습니다.strcat(b4, ", wrld!").

말할 필요도 없이 대부분의 경우,b0형식. 문자를 세는 것은 지루하고 오류가 발생하기 쉽습니다.Brian Kernighan(C를 만든 사람 중 한 명)이 이 맥락에서 썼듯이, "컴퓨터가 더러운 일을 하게 놔둬라."

한가지 더요.다음과 같이 기입:

하여 ' 스토어 명령어'를 만들고 있습니다.a ★★★★★★★★★★★★★★★★★」c 、 are 、 are are are are보다 먼저 됩니다.b에서 の for for for for for for for의 을 \0어레이의 끝에 있습니다.

거기서 무슨 일이 일어나고 있는지는 모르겠지만, 컴파일러가 "이것들을 위한 공간을 마련하려고 하지 않는다"고 말해도 무방합니다.\0컴파일러는 사용자가 선언한 순서, 알파벳 순서, 기타 생각할 수 있는 어떤 변수와도 일치하지 않는 고유한 내부 순서로 변수를 저장할 수 있습니다. 어레이 아래에 b.\0마치 문자열을 종료하는 것처럼, 그것은 아마도 기본적으로 무작위 우연이었을 이다, 컴파일러가 당신에게 친절하게 대하고 무언가를 만드는 것을 도우려고 했기 때문이 아니다.printf("%s\n", b) 정의되어 있습니다해 본 두 아래에 .)printf("%s\n", b)된 ★★★★★★★★★★★★★★★★」hi^E ★★★★★★★★★★★★★★★★★」hi ??는 예측대로 랜덤가비지 후행의 존재를 명확하게 나타내고 있습니다).

당신의 질문에는 두 가지가 있습니다.

  1. 문자열 리터럴문자열 리터럴(큰따옴표로 둘러싸인 것)은 항상 올바른 늘문자 끝 문자열입니다.

    char *p = "ABC";  // p references null character terminated string
    
  2. 문자 배열은 요소 수만큼만 포함할 수 있으므로 3개의 요소 문자열 리터럴을 사용하여 2개의 요소 배열을 초기화하려고 하면 처음에 2개만 기록됩니다.따라서 어레이에는 C 문자열 끝의 null 문자가 포함되지 않습니다.

    char p[2] = "AB";  // p is not a valid C string.
    

문자 배열은 어떤 것으로도 종료할 필요가 없습니다.배열입니다.실제 콘텐츠가 어레이 크기보다 작을 경우 해당 콘텐츠의 크기를 추적해야 합니다.

여기서의 답변은 끈적끈적한 토론으로 전락한 것 같다.모든 char 배열이 문자열인 것은 아닙니다.단, Null 터미네이터를 사실상의 문자열로 취급할 경우에는 이를 센티넬로 사용하는 것은 매우 강력한 규약입니다.

어레이는 다른 것을 사용할 수 있으며 구분 기호와 존이 있을 수도 있습니다.결국 그것은 유니온일 수도 있고 구조물을 덮을 수도 있다.다른 시스템의 집결지일 수도 있습니다.

언급URL : https://stackoverflow.com/questions/69162573/are-char-arrays-guaranteed-to-be-null-terminated

반응형