ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Pointer] 달과 손가락
    개발/C++ 2021. 4. 10. 17:44

    포인터는 주소값을 담는 변수 그 이상 그 이하도 아닙니다. 포인터가 어려운 이유는 주소를 다루는 점 때문에 그렇습니다. 이 모든 건 주소 때문입니다. 개발자가 주소를 직접 다룰 수 있는 언어는, 지금 활발하게 사용되는 언어 중에서는 C/C++가 대표적입니다. typeid를 이용해 타입을 출력해보면 pNum의 공식적인 타입을 확인할 수 있습니다.

    #include <iostream>
    using namespace std;
    
    int main()
    {
       int num0 = 0;
       int* pNum = &num0;
       cout << typeid(&num0).name() << endl;
       cout << typeid(pNum).name() << endl;
    }

     

    포인터에 대해 이야기할 때 배열을 빼놓으면 안 됩니다. nums는 '크기가 3인 int형 배열'이라는 타입을 가집니다. 그렇기 때문에 sizeof로 크기를 출력해보면 제대로 된 배열의 크기를 알 수 있게 됩니다(3 * 4(int형의 크기))

    #include <iostream>
    using namespace std;
    
    int main()
    {
       int nums[] = { 1,2,3 };
       cout << typeid(nums).name() << endl;
       cout << sizeof(nums) << endl;
    }

     

    배열의 이름은 상수 포인터라도 하는데, 엄밀히 말하면 아닙니다. 포인터로 변환이 가능한 것이지, 따로 타입을 지닙니다. 이러한 특수한 변환을 decay(부식, 부패)라고 합니다. nums 배열을 포인터 변수 pNum에 넣으면 배열에 관한 정보를 잃게 됩니다. '크기가 3인 정수형 배열'이라는 타입이 포인터로 바뀌면서 배열의 크기를 알 수 없게 됩니다. 32비트 기준으로 int형 포인터의 크기는 4바이트이기 때문에 sizeof의 값이 4가 됩니다.

    #include <iostream>
    using namespace std;
    
    int main()
    {
       int nums[] = { 1,2,3 };
       int* pNums = nums;
       cout << typeid(pNums).name() << endl;
       cout << sizeof(pNums) << endl;
    }

     

    함수를 정의할 때 다음과 같이 해도 배열의 특성은 사라지게 됩니다.

    #include <iostream>
    using namespace std;
    
    void func(int a[])
    {
    	cout << typeid(a).name() << endl;
    	cout << sizeof(a) << endl;
    }
    
    int main()
    {
    	int nums[3] = { 1,2,3 };
    	func(nums);
    }

     

    다음은 배열과 포인터의 몇 가지 특성입니다. 배열의 이름이 상수의 특징을 가지고 있는 것은 맞습니다. 그 자체로 변경이 불가하기 때문입니다.

     

    출처>

    패스트캠퍼스 C++ 올인원 패키지

    en.cppreference.com/w/cpp/language/array

    댓글

Designed by Tistory.