컴퓨터 공부/© C

[C언어] 7. 포인터

letzgorats 2021. 1. 28. 17:40

- 포인터에서부터 사람들이 C언어를 어려워하는데 전혀 어려운 내용이 아니다!

 인터넷에도 포인터에 대한 자료도 풍부하다. 향후 훌륭한 프로그래머가 되려면 이 '포인터' 공부를 제대로 해놓으면 빛을 볼 수가 있다. 웹개발이나 앱개발 쪽에서는 굳이 몰라도 큰 상관이 없긴 한데, 코어 모듈 개발도 우리는 할 수 있어야 한다! 자 그럼 시작해보장 v^___^

 

7. 포인터

 

- 지금까지의 변수는 "그 자체로 자신의 자료형에 맞는 값"을 저장한다.

ex) int,double 등등

 

- 포인터(Pointer)변수는특이한 변수, “메모리 주소를 저장한다.

ex) int형 변수를 만들 때, 이 변수의 위치값을 가르키는 int형 포인터가 존재할 수 있는 것이다. 포인터는 *(별표시)로 이용해서 나타낼 수 있다. (int*)

 

- 포인터는 메모리의 주소값을 가진다고 보면 된다.

 

(예제 1)

(해설) 기존에 a를 이용해서라도 5라는 값을 찾을 수 있지만 포인터 변수인 b를 이용해서도 5라는 값을 찾을 수 있다. , 포인터를 통해 값을 처리하는 방법이 다양해 졌다고 할 수 있다. 여기서 포인터 변수 b도 변수이기 때문에 특정한 주소를 가진다.

 

- int *b=&a 처럼 선언할 때 쓰는  * (포인터)는 포인터 변수임을 알려준다.

- 선언 한 이후에 *b(여기 * 은 간접 참조 연산자)라고 쓰게 되면, 이것은 포인터 변수 b가 가리키는 주소값의 “진짜을 의미한다.

- 다시말해, 5라는 값 자체가 된다.

(간접참조: 현재 포인터가 가리키고 있는 주소에 들어 있는 값을 참조한다는 뜻)

 

 

<포인터 관련 연산자>

 

- 주소연산자 (&) : 변수 앞에 붙어서 변수의 메모리 시작 주소을 구한다.

- 포인터 (*): 포인터 변수를 선언할 때 사용한다.

- 간접 참조 연산자(*) : 선언된 포인터 변수가 가리키는 변수를 구한다.

 

(예제2)

#include <stdio.h>


int main(void) {

        int a = 5;

        int *b = &a;

        printf("%d\n", *b);

        system("pause");
        return 0;
}

(해설) 선언할 때의 앞선 *b에서의 *나중에 사용할 때의 *b생긴 건 동일하지만 위쪽에 있는 것은 포인터 연산자이고 아래 쪽에 있는 것은 간접 참조 연산자라는 것을 기억하자!

여기서 포인터 변수 ba의 주소값을 가진 값을 할당하는 것이므로 printf문에서도 b가 아닌 *b를 써야한다. 다시말해서, 포인터 변수 b가 가리키고 있는 주소값의 변수값을 출력했다고 할 수 있다.

 

(예제3) 배열 각 원소의 주소값 출력하기

#include <stdio.h>


int main(void) {

        int a[] = { 1,2,3,4,5,6,7,8,9,10 };

        int i;

        for (i = 0; i < 10; i++) {

                printf("%d\n", &a[i]);

        }

        system("pause");
        return 0;
}

(해설) 출력해보면, 배열 각 원소의 주소값이 출력된다. &는 이처럼 특정 원소의 메모리 주소값을 불러온다. 여기서 흥미로운점은, 출력해보면 출력된 주소값이 4씩 차이가 나는 것을 볼 수 있는데, int형은 4바이트를 차지하므로 메모리 주소를 1바이트씩 표현할 때 4칸을 차지한다. , 하나의 정수마다 4bytes의 메모리를 차지하기 때문에 1씩 증가되면서 주소값은 4씩 차이나는게 당연하다고 할 수 있다.배열 a40bytes를 차지하는 배열임을 알 수 있다

 

 

<포인터의 강력한 기능>

 

- 포인터는 컴퓨터 시스템의 특정한 메모리에 바로 접근가능

 

- 따라서, 기존에 존재하던 중요한 메모리 영역에 접근하지 않도록 해야한다.

ex)int *a=0x33484735;  이것은 굉장히 위험한 코드이다.

 특정한 주소값을 바로 포인터 변수가   *a=0;가리키도록 한 다음에 그 값을 0으로 바꿔버리는 코드다. 특정한 주소값에  함부로 접근해서 다른 값을 쓰면 안된다.

 

- 포인터는 다중으로 사용할 수가 있다.

(예제4) 다중 포인터

#include <stdio.h>

 
int main(void) {

        int a = 5;

        int *b = &a;

        int** c = &b;

        printf("%d\n",**c);

        system("pause");
        return 0;
}

(해설) 포인터는 단지 특정한 메모리 주소를 담고 있는 변수일 뿐이다. 따라서, 포인터는 다중으로 사용할 수 있다. 여기서 주의할 점은 *b=&a **c=&b 처럼 &다음엔 포인터 없이 그냥 변수 알파벳만 오면 된다.

 마지막 printf문에서는 그냥 변수 c가 아닌 **c를 출력해줘야 그 주소값이 가리키고 있는 값, 즉 변수a의값을 출력 할 수가 있다.  

 포인터의 포인터, 포인터의 포인터의 포인터 다 가능하다. 실제로 ***d=&c도 해봤는데 똑같이 5가 출력되는 것을 확인했다.

 

 

- 배열과 포인터는 사실 동일하다. 배열을 선언한 이후에는 그 이름자체가 포인터 변수와 동일하다.

(예제5)

#include <stdio.h>

int main(void) {

        int a[] = { 1,2,3,4,5,6,7,8,9,10 };

        int* b =  a;

        printf("%d\n",b[2]);

        system("pause");
        return 0;
}

(해설) 배열을 선언한 이후에는 그 이름 자체를 포인터 변수처럼 쓸 수 있다. 여기서 주의할 점은 int *b= a; 처럼 a는 배열이므로 주소값을 따오는 &a 가 아닌 그냥 a라고 적어줘야 한다.

다시말해, 포인트 변수를 만들어서 a를 가리키도록 만들자.(int *b=a;) 여기서는 주소연산자(&)가 안 붙었지? a라는 일종의 배열 자체를 지금 주소값으로 사용하고 있다는 것이다. 사실 내부적으로 이 배열의 이름자체는 주소값 자체를 가지고 있다. 그렇기 때문에 이렇게 사용한다.

 그럼, *b[2]가 아니라 b[2] 일까? 다시한번 말해준다! 포인터 변수에 배열a를 할당했으니 배열 자체가 주소값을 가지므로 *b가 아니라 b가 와야지! 배열과 포인터는 상호치환이 가능하잖냐! (마지막 페이지 그림 참조)

 

(정리)

1) 포인터는 특정한 변수가 메모리 상에 존재하는 위치주소를 저장한다.

2) 포인터는 특정한 메모리 주소에 바로 접근 할 수 있으므로 조심스럽게 사용해야한다.

3) 배열이 정해지면 그 배열의 이름자체는 주소값 자체를 가지고 있다.

 

▶ 포인터는 변수 자체가 아니라 변수의 주소를 가지고 논다는 것을 기억하면 될 것 같다

반응형

'컴퓨터 공부 > © C' 카테고리의 다른 글

[C언어] 9. 문자열  (0) 2021.02.13
[C언어] 8. 문자  (0) 2021.02.13
[C언어] 6. 배열  (0) 2021.01.28
[C언어] 5. 함수  (0) 2021.01.27
[C언어] 4. 반복문  (0) 2021.01.27