왜 변수에 포인터를 입력해야하는지 ...


#include <stdio.h>
void main()
{
    int a[] = {10,20,30,40,50,60,70,80,90,100};
    int k,m,i,*ptr;
    k=m=0;
    ptr=a;
    for(i=0; i<10; i+=2)
    {
        k+=ptr[i];
        m+=ptr[i+1];
    }
    printf("***** result ***** \n\n");
    printf("(10+30+50+70+90)=%d\n",k); //250
    printf("(20+40+60+80+100)=%d\n",m); //300
}

저기 위 *ptr에서 왜 *을 붙여야 하는지 잘 모르겠습니다.

포인터를 주지 않고 그냥 ptr로 작성해도 괜찮지 않나요?

또한 *를 주었을 때 변수 a[]를 불러오는지 잘 모르겠습니다.

  • 2016년 09월 27일에 작성됨

  • 덕분에 저도 배워갑니다.    이성우   2016.9.27 23:33     
조회수 106


2 답변


안녕하세요! 올려주신 코드는 아래의 방식으로 하셔도 상관 없습니다!

#include <stdio.h>
void main()
{
    int a[] = {10,20,30,40,50,60,70,80,90,100};
    int k,m,i;    //*ptr;
    k=m=0;
    // ptr=a;
    for(i=0; i<10; i+=2)
    {
        k+=a[i];
        m+=a[i+1];
    }
    printf("***** result ***** \n\n");
    printf("(10+30+50+70+90)=%d\n",k); //250
    printf("(20+40+60+80+100)=%d\n",m); //300
}

그리고 배열을 포인터로 받은 이유는 배열 자체가 포인터의 집합이기 때문입니다.

예를 들자면 포인터는 열차의 1개 칸 혹은 동력이 있는 머리 부분이고 배열은 완성된 1개의 열차라고 보시면 됩니다.

따라서 포인터로 배열을 받아 배열처럼 사용하는 것이 가능하기 때문에 그것을 보여주기 위한 코드로 보입니다.

  • 2016년 09월 27일에 작성됨
    C++을 중점으로 배우고 있는 학생입니다. 잘 부탁 드립니다!


위의 답변으로도 충분하지만, 혹시라도 포인터와 배열의 관계에 대해 좀 더 깊이 알고 싶은 분들을 위해 추가적으로 내용을 남깁니다.

int main()
{
    int a[] = {10,20,30,40,50,60,70,80,90,100};
    // 위 코드는 암시적으로 아래 코드로 변환됩니다.
    // int a[10] =  {10,20,30,40,50,60,70,80,90,100};
    // c, c++ 에서 배열 타입은 고정된 크기가 정해져야만 하기 때문입니다.
    // 실제로 a 라는 변수의 타입은 'int [10]' 타입입니다.

    // 그런데 배열 타입은 보기에 좀 복잡해 보이기 때문에 가독성이 떨어집니다.
    // 그래서 보통은 포인터 타입으로 변환해서 사용합니다.
    // c, c++ 에서 배열 타입은 암시적으로 포인터 타입으로 캐스팅할 수 있습니다.

    int* ptr = a; // 때문에 a변수를 다른 변수에 저장하고 싶을 때, 이렇게 씁니다.

    // 하지만 위와 같은 경우 사실 암시적 캐스팅에 의해 배열의 길이 정보를 잃어버리게 됩니다.
    // 배열 타입은 타입 자체에 배열의 크기를 가지고 있다는 점에서 포인터와 다릅니다.

    // 즉, 변수 'a'와 변수 'ptr'은 사실상 같은 값(배열의 시작 주소)를 가지지만,
    // 'a'는 타입자체에 배열길이가 10이라는 정보를 가지고 있고,
    // 'ptr'은 단지 int형 주소값이라는 정보만 가지고 있는 점에서 차이가 생깁니다.

    // 그럼 그 배열길이 정보라는게 어디서 써먹냐? 싶을 수 있는데,
    // c에서의 예제는 이해하기 복잡한 부분이 많기 때문에,
    // c++의 Range-based for loop를 예로 들겠습니다.

    // 이 경우 'a'라는 변수의 타입이 배열의 길이정보를 가지기 때문에 배열을 순회할 수 있습니다.
    for (int i : a)
    {
        i = 0;
    }

    // 하지만 이 경우는 'ptr'이 포인터 타입이기 때문에 길이정보가 없어 배열을 순회할 수 없습니다.
    /*
    for (int i : ptr) // error
    {
        i = 0;
    }
    */

    // 질문에서의 이 부분의 코드가 동작할 수 있는 이유는
    int k,m,i;
    k=m=0;
    for (i = 0; i < 10; i += 2)
    {
        k += ptr[i]; // 여기서의 [ ]는 타입이 아니라 연산자이기 때문입니다.
        m += ptr[i+1];
    }

    // '[ ]' 연산자는 포인터 타입에서도 사용할 수 있으며,
    // 해당 포인터 변수에 저장된 주소로부터 '[ ]' 안에 들어가는 숫자만큼
    // 포인터 연산을 통해 이동한 해당 위치의 값의 참조를 반환하는 연산자입니다.

    // 즉, k += ptr[i] 는 k += *(ptr + i) 와 같은 코드이고,
    // (ptr + i)는 ptr값에 i값을 더한다는게 아니라,
    // ptr값에 (i * sizeof(int))의 결과값을 더한다는 뜻입니다. (포인터 연산)
    // 포인터 연산으로 변경된 위치의 주소값을 '*'연산자를 통해 참조하여 레퍼런스를 반환하게 되며,
    // 반환되는 타입은 int& 타입으로 볼 수 있습니다.

    // 참고로 위의 'a' 변수를 레퍼런스 타입으로 받으려면
    int(&b)[10] = a; //이렇게 써야하며,

    // 배열 타입에 대한 레퍼런스 타입은 배열 타입과 똑같이 사용할 수 있습니다.
    for (int i : b) // ok
    {
        i = 0;
    }

    return 0;
}
  • 2016년 09월 28일에 작성됨
    C++, C# 좋아합니다.

  • 답변해주셔서 감사합니다.    TAEG   2016.9.29 21:46     

로그인이 필요한 기능입니다.

Hashcode는 개발자들을 위한 무료 QnA사이트 입니다. 작성한 답변에 다른 개발자들이 댓글을 작성하거나 좋아요/싫어요를 할 수 있기 때문에 계정을 필요로 합니다.
► 로그인
► 계정만들기
Close