본문 바로가기
C/기초(두들낙서)

[C기초] 포인터 /포인터와 배열

by Meaning_ 2022. 1. 2.
728x90
반응형

포인터

 

포인터는 변수의 주소를 저장하는 변수이다.

 

포인터를 선언하려면 * 를 붙여줌으로써 보통의 변수와 구별해준다. 

 

1
2
3
4
5
6
7
8
9
int main() {
 
    int a = 20;
    int* ptr_a;//포인터 선언
 
    ptr_a = &a; //&는 주소값 즉 a의 주소값을 의미
 
    printf("%d\n", ptr_a);
}
cs

 

int * ptr_a; 는 포인터를 선언해준 것이고

ptr_a=&a;를 해줌으로써 ptr_a라는 변수에 a의 주소값이 들어가게 된다. 

 

*의 두가지의 의미 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include<string.h>
 
int main() {
 
    int a = 20;
    int* ptr_a;//포인터 선언
 
    ptr_a = &a; //&는 주소값 즉 a의 주소값을 의미
 
    printf("a의 값:%d\n", a);
    printf("a의 주소값:%d\n",&a);
    printf("ptr_a에 저장된 값:%d\n", ptr_a);
    printf("ptr_a가 가리키는 변수의 값:%d\n"*ptr_a);
    
 
}
cs

 

int *ptr_a 와 printf안에 있는 *ptr_a는 형태만 같지 의미는 다르다.

 

전자는 컴퓨터에게 포인터를 선언했다고 알려주시 위해 *를 붙인 것이고,

후자는 ptr_a가 가리키는 변수 자체를 가져오라고 한 것이다.  ptr_a는 &a이기에 &a가 가리키는 변수가 a 이기에 *ptr_a==a이다. 

 

*ptr

 

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
#include<string.h>
 
int main() {
 
    int a = 10;
    int* ptr;
    ptr = &a;
    printf("a의 값:%d\n", a);
    *ptr = 20;
    printf("a의 값:%d\n", a);
 
}
cs

 

첫번째와 두번째 출력값은 어떻게 될까?

첫번째는 10이 나올것이다.

*ptr은 ptr이 가리키는 변수, 즉 a를 의미하는데 *ptr=20;을 함으로써 a에 값이 20으로 바뀐다. 

그렇기에 두번째는 20이 나올 것이다. 

포인터를 가리키는 포인터 

int **ptr_ptr; 의 형태로 *가 2번 들어간다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include<string.h>
 
int main() {
 
    int a = 10;
    int* ptr;
    ptr = &a;
    int** ptr_ptr;
    ptr_ptr = &ptr;
    
    printf("ptr_ptr=%d\n", ptr_ptr);
    printf("*ptr_ptr=%d\n"*ptr_ptr);
    printf("**ptr_ptr=%d\n"**ptr_ptr);
}
cs

 

첫번째 출력값은 ptr의 주소값이

두번째 출력값은 ptr_ptr이 가리키는 변수이므로 ptr이

세번째 출력값은 *(*ptr_ptr)인데 ptr_ptr이 가리키는 변수인 ptr 그리고 그 ptr이 가리키는 변수이므로 a가 나온다. 

 

++ 더 알아보기 

 

1번과 2번의 차이점은 무엇일까? 앞에서부터 계속 말했지만

1번은 그냥 포인터 선언이다.

int *ptr_a;

ptr_a=&a; 를 한줄로 적어준 것이다. 

 

2번은 ptr_a가 가리키는 변수가 20이라는 것 즉 a가 20 이라는 것이다.

 

포인터와 배열

 

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
#include<string.h>
 
int main() {
 
    int a = 10;
    int* ptr_a = &a;
 
    printf("ptr_a의 값:%d\n", ptr_a);
    printf("ptr_a+1의 값:%d\n", ptr_a + 1);
 
}
 
cs

 

 

ptr_a +1을 하면 14219933이 되어야하는데 왜 14219936일까? 즉, 왜 4만큼 더해진걸까??

 

a 는 int 이기에 4바이트이다. 램에서는 1바이트(8비트)가 가장 작은 공간이다. 

ptr_a가 a를 가리키고 있는데 거기에 1을 더하면 포인터가 가리키는 자료형의 크기만큼 즉 int의 경우는 4만큼이 더해진다. 

 

 

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include<string.h>
 
int main() {
 
    int arr[10= { 1,2,3,4,5,6,7,8,9,10 };
    printf("arr의 값:%d\n", arr);
    printf("arr+1의 값:%d\n", arr + 1);
 
}
cs

 

arr은 arr[0]의 주소값을 의미하고 arr+1은 arr[0]의 주소값에 4만큼 더한, 즉 arr[1]의 주소값이 나온다. 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include<string.h>
 
int main() {
 
    int arr[10= { 1,2,3,4,5,6,7,8,9,10 };
    
    for (int i = 0; i < 10; i++) {
        printf("&arr[%d]=%d\n", i,&arr[i]);
        printf("arr+%d=%d\n", i, arr + i);
       
    }
 
}
 
cs

이 출력값을 통해 arr+i=&arr[i] 라는 것을 일반화 할 수 있다. 

 

1
2
3
4
for (int i = 0; i < 10; i++) {
        printf("%d\n", arr[i]);
        printf("%d\n", *(arr + i));
    }
cs

두개의 같은 값이 출력되는데

이유는 arr+i=&arr[i]이므로 arr[i]의 주소값이 가리키는 변수는 arr[i]이기에 *(arr+i)는 사실상 arr[i]를 의미한다. 

 

마지막 예제를 보자. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include<string.h>
 
int main() {
 
    int arr[10= { 1,2,3,4,5,6,7,8,9,10 };
    
    
    for (int* ptr = arr; ptr < arr + 10; ptr++) {
        printf("%d\n"*ptr);
    }
 
}
 
cs

 

어떻게 1부터 10까지 출력될 수 있을까? 

 

for (int* ptr = arr; ptr < arr + 10; ptr++)

 

for문 부분을 자세히보자.

int *ptr=arr 이라는 것은 arr이 arr[0]의 주소값이기에 ptr이라는 포인터를 선언하고 그 값을 &arr[0]으로 초기화 한 것이다.

 

ptr<arr+10 이라는 것은 ptr이 &arr[10]이 될 때까지 for문을 돌린다는 것이고

 

ptr++은 ptr+1이기에 사실상 4바이트가 더해지는 것이므로 &arr[i+1]이 ptr이라는 변수에 들어가는 것을 의미한다. 

 

그렇기에 *ptr이면 arr[i]를 의미하는 것이고, arr에 들어있는 원소인 1부터 10이 나오는 것이다. 

 

포인터 연습문제

1) 길이가 5인 int형 배열 arr이 있고 1,2,3,4,5로 초기화 한다. 첫번째 요소를 가리키는 포인터 변수 ptr을 선언한다. 그 다음 포인터 변수 ptr에 저장된 값을 증가시키는 형태의 연산을 기반으로 배열요소에 접근하면서 모든 배열 요소의 값을 2씩 증가시킨다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include<string.h>
 
int main() {
    
   
    int arr[5= { 1,2,3,4,5 };
    int* ptr = arr; //&arr[0]
    for (int i = 0; i < 5; i++) {
        *ptr += 2;//배열 요소의 값 2씩 증가
        ptr++;//ptr+1=&arr[i+1] 즉 ptr이 arr[i+1]의 주소값으로 변함
    }
}
 
cs

 

2) 1번문제에서는 ptr에 저장된 값을 변화시켰는데, 이번에는 ptr에 저장된 값을 변화시키지 않고 모든 배열의 요소를 2씩 증가시키려면 어떻게 해야할까?

 

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
#include<string.h>
 
int main() {
    
   
    int arr[5= { 1,2,3,4,5 };
    int* ptr = arr; //&arr[0]
    for (int i = 0; i < 5; i++) {
        *(ptr+i) += 2//*(ptr+i)는 ptr+i=&arr[i] *(ptr+i)는 arr[i]를 가리킴
    }
}
 
cs

int arr[5]

int *ptr=arr 일때,

ptr=&arr[0]

ptr+1=&arr[1]

*(ptr+1)=arr[1]

 

 

728x90
반응형

'C > 기초(두들낙서)' 카테고리의 다른 글

[C기초] 포인터와 배열 연습문제  (0) 2022.01.08
[C기초] 포인터 배열  (0) 2022.01.04
[C 백준] 브론즈 3/ 세 수  (0) 2022.01.02
[C기초] 배열 포인터  (0) 2022.01.02
[C기초] 배열과 문자열  (0) 2022.01.02

댓글