7월 3주차_C Study 1. 포인터

2023. 7. 22. 15:03language : p_study/c language

7월 3주차 학습 할 C언어 study 목차는 다음과 같다.

 

1. 포인터
2. 문자열

 

1. 포인터

 

포인터란?

메모리의 주소를 가지고 있는 변수이다.

포인터는 변수가 저장되는 주소와 깊은 관계가 있다.

 

변수는 컴퓨터 메모리에 만들어지는데, 이렇게 변수들을 생성하면 메모리 상에 변수들이 배치되게 되는 것이다.

절대적인 주소 값은 시스템에 따라 달라진다.

 

✔ 변수의 주소

 

변수의 주소를 어떻게 알 수 있을까?

  • c언어에는 변수의 주소를 계산하는 연산자 &가 있다.
  • 주소 연산자 &는 변수의 이름을 받아서 변수의 주소를 반환한다.
  • int i ;라고 변수를  정의했다면, 변수 i의 주소는 &i하면 알 수 있다.
  • 포인터란, 가리킨다의 동사 point와 er을 붙인 것이다. 따라서 가리키는 것이라는 뜻인데, 포인터는 변수의 주소를 가지고 있는 변수이다.
  • 포인터가 저장하고 있는 것이 값이 아니라 변수의 주소이다.

 

정수를 가리키는 포인터는 다음과 같이 정의된다.

int * p ;

p는 정수를 가리키는 포인터 이고, 포인터도 변수이다.

따라서 포인터도 사용하기 전에 반드시 선언되어야 하고 초기화하여야한다.

포인터를 선언하려면 포인터가 가리키는 자료형을 쓰고 *를 붙인 다음 변수의 이름을 쓴다.

 

int number = 10 ;
int * p ;
p = &number ;

 

나도 처음에 포인터 학습하기 전에는 다들 포인터부터가 정말 어려워진다고 하길래 겁을 먹었었는데, 포인터라는 개념을 학습하고 나서 왜 어렵다고 하는지 처음에는 몰랐다. 아무래도 제대로 공부가 안된듯

오히려 포인터는 학습할수록 헷갈리는 부분이 많았다.

그래서 도움을 받고자 유투브나 기타등등 많이 찾아봤는데 도움이 많이 되었던 영상을 첨부한다.

 

C언어 기초 프로그래밍 강좌 13강 - 포인터 (Pointer) (C Programming Tutorial For Beginners 2017 #13) - YouTube

 

이 영상을 정말 몇번이고 돌려봤는지 모르겠다. 

쉬우면서도 난해하다고 느꼈던 개념이 바로 포인터는 변수의 주소를 가지고 있는 변수라는 것이다.

그냥 읽어보면 되게 말장난 같은데 이래서 나는 그림을 그리면서 이해했던 것 같다.

 

위그림을 보면 int a ; 로 변수를 선언하는 것을 볼 수 있다.

int *b는 포인터를 선언하는 것이다.

그리고 b= &a 라는 것은 a의 주소값이 b를 나타낸다라는 것인데 a의 주소가 104번지라면 b에 104가 기록된다는 것이다.

이렇게 그림으로 이해를 하면서 주소값이라는 개념을 이해하기 위해 노력을 많이 했다.

아직도 백퍼센트 이해를 하고 사용을 할 수 있는 단계는 아니지만 이정도로 이해를 하고 예제를 계속 풀어보면서 익히는 수밖에..

 

 

간접참조연산자 

 

포인터가 단순히 메모리의 주소만 저장할 수 있는 것이라면 유용하게 쓰이지않을 것이다.

c에서 포인터는 핵심 중에 핵심이기에 유용한 기능이 분명 있을 것인데, 그건 바로 포인터를 통하여 포인터가 가리키는 위치의 값을 읽어오거나 변경할 수 있기 때문이다.

포인터가 p가 가리키는 이치에 저장된 내용을 가져오려면 p앞에 *기호를 붙여서 *p하면 된다.

이것을 포인터를 통하여 간접참조한다 고 한다.

*연산자는 단항 연산자로서 괄호 다음으로 높은 우선순위를 가진다는 점을 참고하자.

 

int number = 10;
int *p;
p = &number;

printf("%d\n" ,*p); // 10이 출력된다.

 

 

포인터 연산자 종류

 

1) 주소 연산자(&)

2) 간접 참조연산자(*)

 

 

포인터 연산

 

포인터에 대해서는 덧셈과 뺄셈만 가능하고, 포인터는 하나를 증가시키면 그대로 1만 증가되는 것이 아니라 자료형의 크기만큼 증가된다.

 

아래가 포인터타입에 따른 증가되는 크기를 나타내는 표이다.

포인터 타입 ++연산후 증가되는 값
char 1
short 2
int 4
float 4
double 8

 

 함수와 포인터

 

 

값에 의한 호출 (call by value)

#include <stdio.h>
void modify(int value)
{
	value = 99; //매개변수를 변경한다.
}

int main()
{
	int number = 1;
    
    modify(number);
    printf("number = %d\n",number);
    
 return 0;
 }

➡ number = 1

 

설명 추가하기

 

 

참조에 의한 호출 (call by reference)

#include <stdio.h>
void modify(int *ptr)
{
	ptr = 99; //매개변수를 통하여 원본을 변경한다.
}

int main()
{
	int number = 1;
    
    modify(&number); //주소를 계산해서 보낸다.
    printf("number = %d\n",number);
    
 return 0;
 }

➡ number = 99

 

기말고사에서 이 부분을 틀렸는데 내가 실수한 부분은 원본을 변경하는 부분.. 원본 변경을 왜 잊었을까..

 

설명 추가하기

 

 

swap() 함수 작성하기

#include <stdio.h>
void swap(int *px, int *py)

int main(void)
{
	int a = 100 , b =200 ;
    printf("swap() 호출전 a=%d b=%d\n, a,b)
    swap(&a ,&b);
    printf("swap() 호출후 a=%d b=%d\n, a,b)
    
    return 0;
 }

void swap(int *px, int *py)
{
	int tmp;
    tmp = *px;
    *px = *py;
    *py = tmp;
    
}

 

swap (&a, &b)   함수 호출시 인수가 a,b가 아니고 &a,&b인 것에 유의해야한다.

 

즉 변수의 값을 전달하는 것이 아니고 변수의 주소를 전달하는 것이다.

swap()에서는 매개 변수 px, py가 전단된 변수의 주소를 받아야한다. 주소를 받을 수 있는 자료형은 포인터이다.

따라서 swap()은 다음과 같이 정의되어야한다.

 

void swap (int *px , int *py) swap()안에서는 tmp라는 임시 변수에 a의 값을 저장하여야한다.

a의 값은 포인터 px을 통하여 얻을 수 있고 px는 &a값을 가지고 있다.

따라서 *px는 a의 값이 된다. 

 

tmp = px* ; ➡ 결과적으로 tmp = a;와 같은 의미이다.

 

다음으로는 포인터를 통하여 b의 값을 a에 저장하는 것이 필요하다.

px과 py가 a와 b를 가리키고 있으므로 다음 문장이 b의 값을 a에 대입한다.

 

*px = *py; // 결과적으로 a=b;와 같은 의미이다.

*py = tmp // 결과적으로 b= tmp;와 같은 의미이다.

 

 

포인터 사용시 주의할 점

 

1) 초기화하지 않고 사용하기

2) 널 포인터의 사용

3) 포인터 자료형과 변수의 자료형은 일치하여야 한다.

 

✔ 배열과 포인터

 

배열과 포인터는 아주 밀접한 관계를 가지고 있다. 

왜냐면 배열 이름 그 자체가 포인터이기 때문이다. 배열 이름은 첫 번째 배열 원소의 주소와 같다.

#include <stdio.h>

int main()
{
	int a[]= {10, 20, 30, 40, 50};
    printf("배열의 이름 =%u\n, a);
    printf("첫 번째 원소의 주소 = %u\n",&a[0]);
    
    return 0;
  }

 

배열의 이름 = 10877424

첫 번째 원소의 주소 = 10877424

 

 포인터를 배열처럼 사용

#include <stdio.h>

int main()
{
	int a[]= {10, 20, 30, 40, 50};
    int *p;
    
    p=a;
    printf("a[0]=%d a[1]=%d a[2]=%d \n", a[0],a[1],a[2]);
    printf("p[0]=%d p[1]=%d p[2]=%d \n", p[0],p[1],p[2]);
    
    return 0;
  
 }

➡ a[0]=10 a[1]=20 a[2]=30
     p[0]=10 p[1]=20 p[2]=30

 

 

+ 추후 codeup을 통해 예제를 올릴 것이다.

 

 

 

 

 

 

 

참고자료: 모두의 C 언어: 8.2 포인터 변수를 사용하는 방법 - 5 (thebook.io)

C언어 기초 프로그래밍 강좌 13강 - 포인터 (Pointer) (C Programming Tutorial For Beginners 2017 #13) - YouTube

'language : p_study > c language' 카테고리의 다른 글

7월 4주차_C Study 1. 구조체  (0) 2023.08.12
7월 3주차_C Study 2. 문자열  (0) 2023.07.22
7월 3 , 4주차_C Study 계획서  (0) 2023.07.20
7월 2주차_C Study 2. 함수  (0) 2023.07.15
7월 2주차_C Study 1. 배열  (0) 2023.07.15