관리 메뉴

IT 컴퓨터공학 자료실

중급편 2. extern 선언의 함정 - 배열과 포인터의 차이점 본문

컴퓨터공학/포인터

중급편 2. extern 선언의 함정 - 배열과 포인터의 차이점

윤맨1 2015. 6. 30. 11:16

                                      포인터 토대가 된 책

                      extern 선언의 함정 - 배열과 포인터의 차이점

이러한 배열과 포인터의 차이를 충분히 머리 속에 넣은 다음, 다음 코드를 보자.

        extern char * str;
        char * p;
        p = str;
(프로그램 2-1)

아무런 특색도없는 코드이지만, str이라는 포인터는 외부 정의가되어있는 것으로되어있다. 그래서이 코드 파일과 다른 파일에서 str의 정의가 이루어지고있는 것이며 링크 할 때 2 개의 파일이 결합되어 하나의 실행 파일이 만들어진다라는 상황 설정이다.

이 때 다른 파일의 str의 정의가

char * str = "test";
(프로그램 2-2)

그렇다면 전혀 문제가 없다. 그러나,

char str [] = { "test"};
(프로그램 2-3)

인 경우는 결코 제대로 작동하지 않는다. 왜냐하면 의사 어셈블러하면,

MOV AX, str의 주소
MOV BX, AX]
MOV [p의 주소, BX
(프로그램 2-4)

라는 식 코드가 생성되는데, 이것은 선언이 배열 인 경우에 기대되는 코드와는 다르다.

MOV AX, str의 주소
MOV [p의 주소, AX
(프로그램 2-5)

즉, 포인터 인 경우에는 여분의 간접 참조가 삽입되게되고, 실제로 포인터 변수 p에 대입되는 값은 다른 것이된다.

이 예제는 사실 매우 찾기 어려운 유형의 버그이다. 의미 론적으로는 대략 어울린다에도 불구하고 약간의 변수 선언의 차이로 미묘한 차이가 버리는 표준적인 예로 자주 꼽힌다. 교훈은 '배열로 선언 된 것은 어디 까지나 배열로 다시 선언'라는 것이며, 아무리 비슷해도 포인터와 배열과 전혀 다른 것이다라는 것이다. 인간은 정확하게 구별하지 않아도 컴파일러는 엄격하게 구분하고있는 것이다.

과제

  1. 아래의 프로그램을 컴파일하고보고 합법적 인 C 언어인지 확인하라. 그러나 합법적 일지라도 결코 모방 할 프로그램이 아니라는 것을 미리주의 해 둔다.그 의미에 대해 생각.
            char * p;
            int num;
            p = "test string"+1;
            p = "test string"[1];
            num = "test string"- "other string";
         / * num = & p [3] - & p [1]; num = (p + 3) - (p + 1); 
           라면 어떨까? * /
    

배열 표기법 & p [3]은 항상 p + 3과 같다. 배열 기법은 흔히 '캔디 (단맛) 문법'이라고 부른다. 그래서 p [-1]라는 표현은 합법적이지만, 제대로 배열 실체에 넌센스가 아님을 확인한다.