목차
이번이 기초 C언어 마지막입니다. ㅜㅜ 그동안 고생많으셨어요
포인터
포인터는 자바나 파이썬이아닌 C에만 있는 개념입니다. 포인터는 메모리에 있는 데이터의 주소를 가지고 있는 변수입니다. 즉 메모리의 주소를 볼 수있는 변수가 포인터입니다. 그걸 왜써요? 간단히 말하면 데이터의 복사를 피하고 데이터를 공유하여 작업하고자 할 때 포인터를 사용하게 됩니다. 예를 들어 누군가가 블랙홀에 대해 질문했을때 백과사전 전체를 복사해 주는 것보다 백과사전의 520페이지를 보라고 알려주는 것이 효율적이죠. 아 몰라요? 늘 그러듯 언젠간 협업을 할 때 메모리가 뻑나서 오류나는 경험을 해보시거나 최적화 작업이 필요할때 C로 작업한걸 감사히 여길때가 올겁니다. 또한 C언어는 저급레벨 즉 임베디드 시스템까지도 커버가 가능합니다. 이러한 이유는 주소까지 만질 수 있기 때문이겠죠.
각설하고 기본 예제를 볼게요.
#include<stdio.h>
int main() {
int i = 10;
double f = 12.3;
char c = 69;
printf("i의주소: %u\n", &i);
printf("c의주소: %u\n", &c);
printf("f의주소: %u\n", &f);
}
- 변수 선언:여기서 세 가지 변수가 선언되고 초기화됩니다:
- i는 값이 10인 정수형 변수입니다.
- f는 값이 12.3인 배정밀도 부동소수점 변수입니다.
- c는 ASCII 값이 69인 문자형 변수입니다 (69는 문자 'E'에 해당합니다).
int i = 10; double f = 12.3; char c = 69;
- 주소 출력:printf 함수를 사용하여 변수 i, c, f의 메모리 주소를 출력합니다. %u 형식 지정자를 사용하여 주소를 부호 없는 정수로 출력합니다.
- &i는 정수 변수 i의 메모리 주소를 나타냅니다.
- &c는 문자 변수 c의 메모리 주소를 나타냅니다.
- &f는 배정밀도 부동소수점 변수 f의 메모리 주소를 나타냅니다.
printf("i의 주소: %u\n", &i); printf("c의 주소: %u\n", &c); printf("f의 주소: %u\n", &f);
다음 보시는 값이 주소값입니다.
포인터의 선언
포인터도 변수입니다. 변수임을 강조하기 위해 때떄로 "포인터 변수"라고도 합니다. 따라서 사용하기전에 선언되어야합니다. 포인터의 이름은 일반적인 변수 이름과 같은 규칙으로 만들면됩니다. 포인터를 선언하려면 포인터가 가리키게 되는 대상을 먼저 쓰고 를 *를 붙인 다음, 포인터의 이름을 씁니다.
int i= 10; //정수형 변수 i선언
p=&i; //변수 i의 주소가 포인터 p로대입
#include<stdio.h>
int main() {
int x = 10, y = 20;
int* p;
p = &x;
printf("p=%d\n", p);
printf("*p=%d\n\n", *p);
printf("x=%d\n\n", x);
p = &y;
printf("p=%d\n", p);
printf("*p=%d\n\n", *p);
printf("y=%d\n\n", y);
}
주소값은 컴퓨터마다 각자 다 다르게 나올 수있습니다. 우연히 같은수도 다를수도있으니 주소값이 다르다고 혼동하지 마세요.
포인터 연산
포인터도 변수이고 메모리의 주소를 값으로 가지고 있으므로 값을 더하거나 뺄 수 있을것 같네여. 실제로 포인터에 대해 덧셈과 뺄셈은 의미 있는 연산자 입니다. 그렇다면 곲셈이나 나눗셈은 어떤가? 주소에 대하여 곱셈이나 나눗셈을 한다는 것은 좀 이상해 보입니다. 실제로 포인터에 대해서는 사칙 연산 중에서 덧셈과 뺄셈만이 허용됩니다.
포인터 타입 | ++ 연산 후 증가되는 값 |
char | 1 |
short | 2 |
int | 4 |
float | 4 |
double | 8 |
#include<stdio.h>
int main() {
int i = 10;
int* pi = &i;
printf("i=%d, pi=%p\n", i, pi);
(*pi)++; //가르키는 값
printf("i=%d, pi=%p\n", i, pi);
printf("i=%d, pi=%p\n", i, pi);
*pi++; //주소증가 +4
printf("i=%d, pi=%p\n", i, pi);
return 0;
}
- 주소 및 값 출력:printf 함수는 i의 값과 pi가 가리키는 주소를 출력합니다. %d는 정수를, %p는 포인터(주소)를 출력하는 형식 지정자입니다.
printf("i=%d, pi=%p\n", i, pi);
- 값 증가:(*pi)++는 pi가 가리키는 값을 1 증가시킵니다. 이 경우, pi는 i를 가리키기 때문에 i의 값이 10에서 11로 증가합니다.
(*pi)++; //가르키는 값 증가 printf("i=%d, pi=%p\n", i, pi);
- 포인터 주소 증가:*pi++는 포인터 pi의 주소를 다음 정수 메모리 위치로 이동시킵니다. 정수형 포인터가 가리키는 주소는 4바이트씩 증가하므로 pi의 값이 4 증가합니다. 이 줄에서는 i의 값은 변하지 않고 pi의 주소만 변경됩니다.
*pi++; //주소 증가 +4 printf("i=%d, pi=%p\n", i, pi);
- 포인터 주소 증가:*pi++는 포인터 pi의 주소를 다음 정수 메모리 위치로 이동시킵니다. 정수형 포인터가 가리키는 주소는 4바이트씩 증가하므로 pi의 값이 4 증가합니다. 이 줄에서는 i의 값은 변하지 않고 pi의 주소만 변경됩니다.
참조에 의한 호출
변수의 복사본이 함수로 전달되는 것이 아니라 원본이 직접 전달되는 거슨 참조에 의한 호출입니다. 변수의 원본이 전달되기 때문에 호출된 함수 안에서 매개 변수의 값을 수정하면 원래의 변수가 똑같이 수정됩니다. C언어에서 참조에 의한 호출이 필요한 경우 포인터를 이용하여 참조에 의한 호출을 구현 할 수있습니다.
#include<stdio.h>
void swap(int* px, int* py)
{
int tmp;
tmp = *px;
*px = *py;
*py = tmp;
}
int main() {
int a = 100, b = 200;
printf("a=%d b=%d\n", a, b);
swap(&a, &b);
printf("a=%d b=%d\n",a, b);
return 0;
}
스왑 함수:
void swap(int* px, int* py)
{
int tmp;
tmp = *px;
*px = *py;
*py = tmp;
}
swap 함수는 두 정수형 변수의 값을 서로 바꾸는 함수입니다. 두 개의 정수형 포인터 (px, py)를 매개변수로 받습니다.
- tmp 변수는 일시적으로 값을 저장하기 위한 용도로 사용됩니다.
- tmp에 *px의 값을 저장합니다.
- *px에 *py의 값을 저장합니다.
- *py에 tmp의 값을 저장합니다.
포인터와 배열
포인터는 배열처럼 사용이 가능합니다. 포인터도 배열 이름처럼 간주될 수있고 배열과 똑같이 사용할 수있습니다. 사실 이것은 상당히 편리한 기능입니다.
#include<stdio.h>
int main() {
int arr[5] = { 10, 20, 30, 40, 50 }; // 정수 배열 선언 및 초기화
int* ptr = arr; // 포인터를 배열의 첫 번째 요소로 초기화
// 배열 표기법을 사용하여 배열 요소 출력
for (int i = 0; i < 5; i++) {
printf("arr[%d] = %d\n", i, arr[i]);
}
// 포인터 표기법을 사용하여 배열 요소 출력
for (int i = 0; i < 5; i++) {
printf("*(ptr + %d) = %d\n", i, *(ptr + i));
}
return 0;
}
- 변수 선언 및 초기화:
- arr은 5개의 정수형 요소를 가진 배열로 선언되고 초기화됩니다.
- ptr은 배열 arr의 첫 번째 요소를 가리키는 정수형 포인터입니다.
int arr[5] = {10, 20, 30, 40, 50}; // 정수 배열 선언 및 초기화 int* ptr = arr; // 포인터를 배열의 첫 번째 요소로 초기화
- 배열 표기법을 사용하여 배열 요소 출력:이 for 루프는 배열 표기법을 사용하여 배열 arr의 각 요소를 출력합니다. arr[i]는 배열 arr의 i번째 요소에 접근합니다.
for(int i = 0; i < 5; i++) { printf("arr[%d] = %d\n", i, arr[i]); }
- 포인터 표기법을 사용하여 배열 요소 출력:이 for 루프는 포인터 표기법을 사용하여 배열 arr의 각 요소를 출력합니다. *(ptr + i)는 포인터 ptr이 가리키는 주소에 i를 더한 위치에 있는 값을 가리킵니다.
for(int i = 0; i < 5; i++) { printf("*(ptr + %d) = %d\n", i, *(ptr + i)); }
'IT' 카테고리의 다른 글
기초컴퓨터프로그래밍 C언어(10)-탐색 (0) | 2025.01.13 |
---|---|
기초컴퓨터프로그래밍 C언어(9)-배열 (0) | 2025.01.10 |
C언어 팩토리얼구하기 (0) | 2025.01.08 |
기초컴퓨터프로그래밍 C언어(8)-함수 (0) | 2025.01.08 |
기초컴퓨터프로그래밍 C언어(7)-중첩반복문、삼각형 별찍기 (0) | 2025.01.06 |