배열과 문자열의관계 C언어

C언어는 문자를 배열로 다룬다.

문자열은 말그대로 문자들의 나열이다.

이곳에서 주로 다룰 내용은 기초적인 내용보다는, 공부를 해나가면서 상식적(자연스럽게)으로 이해하기 힘든내용을 요약정리해두겠다.

배열의 기본 문법은 안다는 전제하에 설명을 하겠다.

배열로 문자열를 다루는 법

일반적인 설명보다는, 예를 들어설명하겠다.

 

char a='a'; // 문자를 다루는 '따옴표다 문제없이 a변수에 a가 입력된다.

char a="a"; // 에러가난다 a를 "로묶어놨기때문에 문자열로 인식한다.  이상태에서에러가 안나게 고치려면?

char*a="a"// 문자열로 인식하고 에러가 안 난다.

그럼 왜 포인터로 선언하면 에러가 안나는걸까. C에서는 String형이 없다. 위와같이 char 형이다.

그래서 C에서는 문자열 인식 메커니즘이 문자열의 시작점을 주소로 반환하는 형태이기때문에 (문자열은 끝에는 \0이온다.) 포인터형이다.

char arr[10]="test" // 에러가 안난다. 문자열과 배열은 아주 밀접한 관계가있다.

char arr[10]={"test","what"}; //에러가 난다.

char *arr[10]={"test","what"} //에러가 안 난다.

에러가 나는 이유는 문자열 자체는 1차원 배열과 마찬가지이다. 그런데 1차원 배열은 1개인데 문자열은 2개가 대입되었다.  하나의 배열공간은 char형으로 1바이트인데 문자열은 최소 1바이트이므로 이런 대입은 불가능하다.

그 다음 포인터 선언을 하니 에러가 없어졌다. 간단히 말해서 포인터 선언을 하므로서 문자열을 저장할수 있는 공간을 10개로 만들어 버렸기 때문에다. 하나의 배열요소는 하나의 포인터가 된 셈이다.

메커니즘만 잘 파악하면 배열에 포인터 선언을 보고 겁먹을 필요는 없을 것이다.

 

수정: 현재 줄친 표현은 최신 C++컴파일러상에선 deprecated conversion from string constant  to char* ~~

이렇게 에러가 난다.

예전에 이런 형식이 가능했다는것이 에러를 발생할 소지가 있었다는것은 알고 있었다.

결국 컴파일러상에서 이런표현을 에러로 고쳤나보다.

<gcc 버전 4.8.1>

반응형

'프로그래밍 > C언어' 카테고리의 다른 글

C언어 strcpy의 구현문제  (0) 2013.05.19
C언어 getch  (0) 2013.05.18
const 키워드  (0) 2013.05.18
난수생성 C언어  (0) 2013.05.16
프로그램 실행시간을 알게하는 코드 C언어  (0) 2013.05.16
배열과 문자열의관계 C언어  (5) 2013.04.29
이 댓글을 비밀 댓글로
  1. 예를들어
    char* a;
    scafn("%s",a);
    이런코드는 실행은되지만 비정상적인 종료를 하게된다.
    신기한점은 세문자까지는 정상실행, 4문자는 정상실행후 대기모드, 5문자를 입력하면 정살실행후 비정상 정료이다.
    근데 이 비정상종료는 printf 문이 실행문의 제일 마지막에 있을 경우이다.
    이경우 포인터변수를 그냥 아무 배열로만 바꿔주면되는데.
    그러면 배열의 크기보다 더 긴 문자열을 넣어도 잘리지않고 입력이된다.
    추측이다.
    대입 연산자의 오버로딩이 적용되어 자동으로 입력 문자값의 길이의 배열길이로 늘린후 대입을 시키는 듯하다.

    그럼 처음으로 돌아가서 포인터 변수에 문자열을 입력시킬경우..
    실행은 되지만 무언가 불완전하다. \n문자의 위치가 정해지지 않아서 그런듯하다. strlen(a)로 입력 문자열의 길이가 반환되는 걸 보면 \n 문자열이 있는 것도 같지만 비정상종료가 되는 걸보면 이상하다.
    좀더 연구해야하겠지만.
  2. 내가 여러가지 실행을 해보고 결론을 내린 메커니즘은..
    포인터 변수은 기본적으로 길이가 3인 문자열까지 안전하게 인식한다.
    하지만 4문자길이를 넘어가면 비정상 종료하게될 수 있다.(printf문이 마지막있을시)
    나는 입력한 문자열의 정보를 얻으려 포인터 변수를 사용하다 이런 문제가 생겼다. 결론은 문자열을 다루는데 포인터 변수와 배열은 메커니즘이 다르기때문이라 생각한다.
    더 확장해보면 포인터변수대신 여러개의 문자열을 받을수 있는 1차원포인터 배열을 생성해서 문자열을 받을시, "직접입력" 직접 입력해서 대입하는 것과 scanf로 입력해서 대입할때가 다르다는 걸 알았다.
    "" 입력시에는 안전하게 대입이되고 출력도 되었다.
    하지만 입력을 받을시에는 불완전하게 입력이 되었다.
    1차원 포인터배열로 다중의 문자를 for문으로 돌려서 받으려고 했었는데
    이경우도 문자열이 입력되는 공간은 명시적선언한 배열이 아니기때문이다.
    결론은 명시적 배열선언을 하는게 가장 안전한것같다..
  3. 실험
    char* a;
    // scanf("%s",a); // ㄱ
    // a="abcdefg"; // ㄴ
    ㄱ과 ㄴ의 경우
    ㄱ의 경우 비정상 종료
    ㄴ의경우 정상적 출력 정상종료
    문자열을 다룰때는 주의할것이있는데 문자열의 길이를 우리가 입력하기전에 명시적으로 알수있게 해야한다.
  4. char* a[2];
    *a[0]='a';
    a[1]="efgh";
  5. #include <stdio.h>

    int main()
    {

    char* a[10];
    scanf("%s", a[0]);
    scanf("%s", a[1]);
    scanf("%s", a[2]);
    scanf("%s", a[3]);
    // scanf("%s", a[4]);
    printf("%s",a[0]);
    printf("%s",a[1]);
    printf("%s",a[2]);
    printf("%s",a[3]);
    /// printf("%s",a[4]);
    // printf("%s",a[5]);

    }