주차 | 진도 | 기본 숙제 | 추가 숙제 |
6주차(8.12~8.18) | Chapter 9 | 포인터의 핵심 내용을 정리하고 공유하기 | CH09 도전 실전 예제(p289) 풀고 인증하기 |
<기본 숙제: 포인터의 핵심 내용을 정리하고 공유하기 >
① 포인터: 메모리 주소 저장하는 변수.
② 포인터의 값 = 포인터가 가리키는 변수의 주소
③ 간접 참조 연산자/포인터 연산자(*): 포인터가 가리키는 변수를 사용할 때(포인터 통해 변수에 접근할 때)
④ 포인터의 크기: 저장할 주소의 크기에 따라 결정됨
⑤ 포인터끼리 대입 가능: 가리키는 주소의 자료형이 같을 때 / 또는 형 변환을 통해 자료형을 같게 만들어주면 가능
<추가 숙제: Ch09 도전 실전 예제(p289) 풀고 인증하기>
[코드]
#include <stdio.h>
void sawp(double* pa, double* pb); // 두 실수를 바꾸는 함수
void line_up(double* maxp, double* midp, double* minp);
int main() {
double max, mid, min;
printf("실수값 3개 입력: ");
scanf("%lf %lf %lf", &max, &mid, &min);
line_up(&max, &mid, &min);
printf("정렬된 값 출력: %.1lf, %.1lf, %.1lf\n", max, mid, min);
return 0;
}
void sawp(double* pa, double* pb) {
double temp;
temp = *pa;
*pa = *pb;
*pb = temp;
}
void line_up(double* maxp, double* midp, double* minp) {
if (*maxp < *midp) {
sawp(maxp, midp); // *maxp와 *midp 정렬 완료
}
if (*maxp < *minp) {
sawp(maxp, minp); //*maxp와 *minp 정렬 완료
}
if (*midp < *minp) {
sawp(midp, minp); //*midp와 *minp 정렬 완료
}
}
[실행 결과]
Chapter 9. 포인터
1. 포인터의 기본 개념
변수: 선언된 블록 {} 내에서만 사용 가능 → 포인터 이용해 사용 범위 외부에서도 변수에 접근 가능
1) 메모리의 주소
메모리 주소: 메모리의 위치 식별. 바이트 단위
e.g) int a;
주소값 | 0 | 1 | … | 10 | 11 | 12 | 13 | … |
메모리 | a가 | 저장된 | 메모리 | 공간 |
2) 주소 연산자
주소: 변수가 할당된 메모리 공간의 시작 주소 주소 연산자(&)로 접근
[코드]
#include <stdio.h>
int main() {
int a;
double b;
char c;
printf("int형 변수의 주소 : %u\n", &a);
printf("double형 변수의 주소 : %u\n", &b);
printf("char형 변수의 주소 : %u\n", &c);
return 0;
}
[실행 결과]
3) 포인터와 간접 참조 연산자
포인터: 메모리 주소 저장하는 변수.
간접 참조 연산자/포인터 연산자(*): 포인터가 가리키는 변수를 사용할 때(포인터 통해 변수에 접근할 때)
[코드]
#include <stdio.h>
int main() {
int a;
int* pa; // int형 변수를 가리키는 포인터 선언
pa = &a; // 포인터에 a의 주소 대입
*pa = 10; // 포인터로 변수 a에 10 대입
printf("포인터로 a값 출력 : %d\n", *pa);
printf("변수명으로 a값 출력 : %d\n", a);
return 0;
}
[실행 결과]
즉, 포인터 pa의 값 = 변수 a의 주소
*pa == a
4) 여러 가지 포인터 사용해 보기
[코드]
#include <stdio.h>
int main() {
int a = 10, b = 15, total;
double avg;
int *pa = &a, *pb = &b;
int* pt = &total; // pt → total: 포인터 pt는 변수 total을 가리킨다
double* pg = &avg; // pg → avg: 포인터 pg는 변수 avg를 가리킨다
*pt = *pa + *pb;
/*
pt가 가리키는 변수(total)에
pa가 가리키는 변수(a)의 값 + pb가 가리키는 변수(b)의 값 대입
*/
*pg = *pt / 2.0; // pg가 가리키는 변수(avg)에 pt가 가리키는 변수(total) / 2.0 대입
printf("두 정수의 값 : %d %d\n", *pa, *pb);
printf("두 정수의 합 : %d\n", *pt);
printf("두 정수의 평균 : %.1lf\n", *pg);
return 0;
}
[실행 결과]
5) const를 사용한 포인터
const 포인터: 포인터가 가리키는 변수의 값을 간접 참조를 통해서는 바꿀 수 없음(즉, 포인터를 이용해 변수의 값을 바꿀 수 없음). 변수의 값을 직접 바꾸는 것은 가능.
[코드]
#include <stdio.h>
int main() {
int a = 10, b = 20;
const int* pa = &a; // 포인터 pa는 변수 a를 가리킨다
printf("변수 a의 값 : %d\n", *pa); // 포인터를 간접 참조해 a 출력
pa = &b; // 포인터가 변수 b를 가리키게 한다
printf("변수 b의 값 : %d\n", *pa); // 포인터를 간접 참조해 b 출력
pa = &a; // 포인터가 변수 a를 가리키게 한다
a = 20; // a를 직접 참조해 값을 바꾼다
printf("변수 a 값: %d\n", *pa); // 포인터를 간접 참조해 바뀐 a값 출력
return 0;
}
[실행 결과]
2. 포인터 완전 정복을 위한 포인터 이해하기
포인터의 특징
① 변수의 주소 저장
② 포인터끼리 대입 가능
③ 대입 연산 기준 엄격
1) 주소와 포인터의 차이
주소: 메모리 저장 공간의 시작 주소 값 자체(상수)
포인터: 주소를 저장하는 또 다른 메모리 공간(변수)
→ 여러 개의 포인터가 하나의 변수를 동시에 가리키는 일도 가능
e.g.
int a; int *pa, *pb, *pc; pa = pb = pc = &a; |
2) 주소와 포인터의 크기
포인터의 크기: 저장할 주소의 크기에 따라 결정됨
[코드]
#include <stdio.h>
int main() {
char ch;
int in;
double db;
char* pc = &ch;
int* pi = ∈
double* pd = &db;
printf("char형 변수의 주소 크기: %d\n", sizeof(&ch));
printf("int형 변수의 주소 크기: %d\n", sizeof(&in));
printf("double형 변수의 주소 크기: %d\n", sizeof(&db));
printf("char * 포인터의 크기: %d\n", sizeof(pc));
printf("int * 포인터의 크기: %d\n", sizeof(pi));
printf("double * 포인터의 크기: %d\n", sizeof(pd));
printf("char * 포인터가 가리키는 변수의 크기: %d\n", sizeof(*pc));
printf("int * 포인터가 가리키는 변수의 크기: %d\n", sizeof(*pi));
printf("double * 포인터가 가리키는 변수의 크기: %d\n", sizeof(*pd));
return 0;
}
[실행 결과]
3) 포인터의 대입 규칙
(1) 가리키는 변수의 형태가 같을 때만 대입
e.g. 허용되지 않는 포인터의 대입
#include <stdio.h>
int main() {
int a = 10;
int* p = &a; // 포인터 p: int형 변수 a의 주소 저장
double* pd;
pd = p; // 포인터 p값(int형 변수의 주소)을 포인터 pd(double형 변수를 가리킴)에 대입
printf("%lf\n", *pd); // pd가 가리키는 변수의 값 출력
return 0;
}
(2) 형 변환을 사용한 포인터의 대입은 가능
#include <stdio.h>
int main() {
double a = 3.4;
double* pd = &a; // pd가 double형 변수 a를 가리키도록
int* pi;
pi = (int*)pd; // pd 값을 int로 변환해 pi에 대입
printf("%p\n", pi);
return 0;
}
4) 포인터를 사용하는 이유
임베디드 프로그래밍(하드웨어 제어하는 소프트웨어 만듦), 동적 할당한 메모리에 접근 등을 위해 포인터 필요!
(1) 두 변수의 값을 바꾸며 포인터 이해하기
e.g. 포인터를 사용한 두 변수의 값 교환
[코드]
#include <stdio.h>
void VarSwap(int a, int b);
void PointSwap(int* pa, int* pb);
int main() {
int a = 10, b = 20;
printf("바뀌기 전 - a: %d, b: %d\n", a, b);
// 일반 변수로는 값 교환이 불가함
VarSwap(a, b); //a, b의 값을 복사해서 전달
printf("일반 변수 - a: %d, b: %d\n", a, b);
// 포인터 이용해 두 변수의 값 교환
PointSwap(&a, &b);
printf("포인터 이용해 변수의 값 교환 - a: %d, b: %d\n", a, b);
return 0;
}
void VarSwap(int a, int b) {
int temp;
temp = a;
a = b;
b = temp;
}
void PointSwap(int* pa, int* pb) {
int temp;
temp = *pa;
*pa = *pb;
*pb = temp;
}
[실행 결과]
'혼공단 12기(혼공C)' 카테고리의 다른 글
[혼공C] 회고록 (0) | 2024.08.18 |
---|---|
[혼공C] 5주차 배열 (0) | 2024.08.06 |
[혼공C] 4주차 함수 (0) | 2024.07.28 |
[혼공C] 3주차 선택문, 반복문 (3) | 2024.07.20 |
[혼공C] 2주차 변수와 데이터 입력, 연산자 (2) | 2024.07.14 |