일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- SQL
- 백준 1987
- Python
- MySQL
- 명품자바
- 그래프
- 모각코
- HUFS 모각코 캠프
- 그리디
- ubuntu
- 백준 17451번
- javascript
- 백준 3085번
- 백준 1331번
- 머신러닝과 딥러닝
- 자바
- react
- java_programming
- 다이나믹프로그래밍
- 백준 1253번
- 백준 18310번
- 알고리즘
- SWEA 15612번
- 백준 2512번
- 다이나믹 프로그래밍
- 백준 15787번
- 백준 16918번
- AWS
- 백준
- 깃헙
- Today
- Total
차곡차곡
[C/L] 포인터 본문
포인터란?
메모리의 주소를 가지고 있는 변수. 즉, 포인터가 저장하고 있는 것은 값이 아닌 변수의 주소이다. 포인터도 변수이기 때문에 사용하기 위해서는 먼저 선언을 해야 하는데, 포인터를 선언할 때 포인터가 가리키는 자료형을 함께 작성해야 한다. int형 포인터는 int형 변수만, char형 포인터는 char형 변수만 가리킬 수 있는 것이다.
int number = 10; // 정수형 변수 number 선언
int *p; // 정수를 가리키는 포인터 p
p = &number; // 변수 number의 주소가 포인터 p로 대입
간접 참조 연산자 *
포인터를 통하여 포인터가 가리키는 위치의 값을 읽어오거나 변경할 수 있는데, 이때 필요한 것이 * 기호이다. 포인터가 가리키는 위치에 저장된 값을 가져오려면 변수 앞에 * 기호를 붙여야 한다.
printf("%d\n", *p) // 10이 출력된다.
* 의 용도
1. 포인터 선언할 때
2. 해당 주소의 값에 접근할 때
포인터 연산
포인터에서 대해서는 덧셈과 뺄셈 연산만 가능하다. 만약 증감 연산자를 사용하여 연산을 하면 항상 1만큼 연산되는 것이 아니라, 가리키는 객체의 크기만큼 증감된다. 즉 char형 포인터를 증가시키면 char형의 크기인 1바이트만큼 증가하고, int형 포인터를 증가시키면 int형의 크기인 4바이트만큼 증가한다.
포인터 타입 | 증감되는 값 |
char | 1 |
short | 2 |
int | 4 |
float | 4 |
double | 8 |
함수와 포인터
C언어는 기본적으로 '값에 의한 호출'만 가능하다. 즉 함수 안에서 매개 변수를 변경하더라도 원본 변수는 변경되지 않는다. 하지만 포인터를 함수에 전달하면 '참조에 의한 호출'을 흉내낼 수 있다.
- 값에 의한 호출(call-by-value) : 함수가 호출될 때 복사본이 함수로 전달되면 값에 의한 호출이다. 함수 안에서 매개 변수를 변경하여도 원본에는 영향을 주지 않는다.
- 참조에 의한 호출(call-by-reference) : 만약 함수가 호출될 때 원본을 함수로 전달하는 방법이다. 함수 안에서 매개변수를 변경하면 원본 변수가 변경된다.
#include <stdio.h>
void modify(int *ptr)
{
*ptr = 99; // 매개 변수를 통하여 원본을 변경한다.
}
int main(void)
{
int number = 1;
modify(&number); // 주소 전달
printf("number = %d\n", number); // number = 99 이 출력된다.
return 0;
}
포인터 사용시 주의할 점
- 초기화하지 않고 사용하기 : 포인터가 선언만 되고 초기화가 되지 않았다면 포인터는 임의의 주소를 가리키게 된다. 따라서 이런 상태에서 포인터를 이용하여 메모리의 내용을 변경한다면 문제가 발생할 수 있다. 포인터가 아무것도 가리키고 있지 않을 때는 NULL(0)로 설정하는 것이 바람직하다. NULL은 stdio.h에 정수 0으로 정의되어 있다.
int *p = NULL;
- 포인터 자료형과 변수의 자료형은 일치하여야 한다 : 포인터는 메모리의 어디든지 가리킬 수 있지만 포인터에 의하여 참조되는 객체가 얼마만큼의 크기이고 무엇이 어떤 형식으로 저장되어 있는지를 결정하는 것은 포인터의 자료형이다.
배열과 포인터
배열 이름이 포인터라면 포인터도 배열 이름처럼 간주되고 배열과 똑같이 사용할 수 있다.
#include <stdio.h>
int main(void)
{
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]); // a[0]=10 a[1]=20 a[2]=30
printf("p[0]=%d p[1]=%d p[2]=%d \n", p[0], p[1], p[2]); // p[0]=10 p[1]=20 p[2]=30
return 0;
}
어떤 경우에 포인터를 배열처럼 사용할까? 만약 대용량의 데이터가 필요한 함수가 있다고 했을 때 모든 데이터를 복사해서 전달하면 시간이 너무 많이 걸릴 것이다. 이런 경우에 데이터가 있는 위치만 전달하여 필요한 부분만 사용할 수 있도록 한다. 배열을 전달받을 때 매개변수를 포인터 변수로 해주면 배열이 복사되지 않고 배열의 주소가 전달된다.
#include <stdio.h>
void sub(int *ptr)
{
printf("%d \n", ptr[10]); // 11이 출력된다.
}
int main(void)
{
int large_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
sub(large_data);
return 0;
}
** 포인터를 사용하는 가장 큰 이유는 넘겨야 할 값이 방대할 경우 주소 값만 알려주는 것이 더 간결하기 때문이다. 데이터를 전부 복사해서 함수로 넘기는 것보다 데이터가 있는 위치를 포인터로 알려주는 것이 더 효율적이다.
'Language > C' 카테고리의 다른 글
[C/L] 문자열 (0) | 2022.12.11 |
---|---|
[C/L] 수식과 연산자 (0) | 2022.07.20 |
[C/L] 변수와 자료형 (0) | 2022.07.09 |
[C/L] C언어 기초 (4) | 2022.07.03 |