본문 바로가기

C

혼공C 6주차

드디어 끝이네요! ( 남아있는 10개의 챕터를 애써 무시한 채... )

악명 높은 포인터 공부 시작해보겠습니다!


숙제

더보기

기본 숙제

<포인터의 핵심 내용 정리 공유>

포인터 : 변수와는 달리 선언된 블록이 아니더라도 데이터가 공유 가능한 메모리 접근 방법

선언 방법 :  자료형 *포인터명; (자료형 *포인터명 = &변수명;)

일반 변수 a, 그를 가리키는 포인터를 pa라 할때,
a = *pa : 변수 a를 의미
&a = &*pa = pa : 변수 a의 시작 주소를 의미

주소 : 시작 주소 값 자체 (상수)
포인터 : 주소 값을 저장하는 메모리 공간 (변수)

포인터 크기 = 주소 값의 크기 =/= 변수의 크기(자료형이 결정)

(자세한 내용은 아래...ㅎ)

추가 숙제

도전) 미니 정렬 프로그램

키보드로 실수 3개를 입력한 후 큰 숫자부터 작은 숫자로 정렬한 뒤 출력하는 프로그램을 작성합니다. 다음 코드와 출력 결과를 참고해 line_up 함수를 작성하세요. line_up 함수에는 이미 정의된 swap 함수를 호출해 구현하세요.


Chap 9 포인터

시스템 프로그래밍이 가능하도록 도와주는 포인터
메모리 주소의 개념과 주소 연산자 &, 간접 참조 연산자 *
포인터 기본 사용법과 포인터 사용 규칙

9-1 포인터 기본 개념

지금까지 변수를 사용해서 메모리에 접근.
    변수 선언으로 메모리에 공간 확보.
    확보한 공간에서 데이터 넣고 꺼내씀.
    변수명으로 이런 메모리 공간 식별

그러나 선언된 블록 { }, 즉 함수 내부에서만 그 변수를 사용할 수 있음.
같은 변수명을 사용했더라도 함수가 다르면 별도의 저장 공간을 확보하므로 전혀 다른 변수로 사용됨.

포인터는 사용 범위를 벗어난 경우에도 데이터를 공유할 수 있게 함.

메모리의 주소

프로그램이 사용하는 메모리의 위치를 주소 값으로 식별.

주소 값
    바이트 단위로 구분
    0부터 시작하고 바이트 단위로 1씩 증가
    2바이트 이상의 크기를 갖는 변수는 여러 개의 주소 값에 걸쳐 할당됨.

주소 연산자

주소 :  변수가 할당된 메모리 공간의 시작 주소

시작 주소를 알면 그 위치부터 변수의 크기만큼 메모리를 사용할 수 있음.

주소 연산자 & 사용

9-1 직접 해보는 손코딩

+) 메모리 주소의 출력 변환 문자
주소는 보통 16진수로 표기함.
따라서 주소를 출력할 때는 전용 변환 문자인 %p 사용하는 것이 좋음.

포인터와 간접 참조 연산자

메모리 주소는 필요할 때마다 계속 주소 연산을 수행하는 것보다 한 번 구한 주소를 저장해서 사용하면 편리

포인터가 바로 메모리 주소를 저장하는 변수

일반 변수와 마찬가지로 선언 후 사용

선언할 때 변수 앞에  * 붙여주면 됨.

9-2 직접 해보는 손코딩

`자료형 *변수명;`

포인터가 어떤 변수의 주소를 저장한 경우 '가리킨다'라고 말함.
둘의 관계를 pa → a 처럼 화살표로 간단히 표현.

포인터가 어떤 변수를 가리키면 포인터로 가리키는 변수를 사용할 수 있음.
즉, 포인터 pa로 변수 a 사용 가능

포인터가 가리키는 변수를 사용할 때는 포인터에 특별한 연산자를 사용하는데,
이를 간접참고연산자 * 또는 포인터 연산자라고 함.

scanf 함수를 사용할 때, 입력할 변수의 주소를 인수로 줘야 하기 때문에, &변수(a) 나 포인터(pa)를 줘야한다.

&a = &*pa = pa

a = *pa

여러가지 포인터 사용해보기

9-3 직접 해보는 손코딩

const를 사용한  포인터

const 예약어를 포인터에 사용하면 이는 가리키는 변수의 값을 바꿀 수 없다는 의미.

9-4 직접 해보는 손코딩

포인터 pa를 선언할 때 const로 상수화 함.

일반 변수처럼 다른 변수의 주소 값을 못 저장하지 않음.

포인터에 사용된 const의 의미는 pa가 가리키는 변수 a는 pa를 간접 참조해 바꿀 수 없다는 것. 그니까... a를 못 바꾸지 pa는 바꿀 수 있게 함.

포인터를 통해서만 바꿀 수 없으며 변수 a 자체를 사용하면 얼마든지 바꿀 수 있음.

문자열 상수를 인수로 받는 함수에서 문자열 상수는 값이 바뀌면 안 되므로 함수의 매개변수를 통해서 값을 바꿀 수 없도록, 매개변수로 선언된 포인터에 const를 사용함.


확인 문제

1. 다음 각 변수의 주소를 저장할 포인터를 선언하세요(변수명은 p로 합니다.)

① char *p;
② int *p;
③ double *p;

2. 다음과 같이 변수가 초기화되고 메모리에 할당되었다고 가정하고 주소 연산자와 간접 참조 연산자를 사용한 수식의 결괏값을 적으세요.

100
101
105
'A'
10
3.4

*&ch는 &ch의 연산의 결과인 주소 100에 다시 간접 참조 연산을 수행해서 주소 위치의 변수 ch의 값이 됨.

3. 다음 코드의 실행결과를 적으세요.

A : 20이 출력 될 것. *p = 20 포인터가 가리키는 변수 a에 20을 대입 했으므로...


9-2 포인터 완전 정복을 위한 포인터 이해하기

포인터는 주소를 저장하는 일정한 크기의 메모리 공간. 다른 주소를 저장하거나 포인터끼리 대입할 수 있음.

포인터는 일반 변수와 달리 대입 연산에 엄격한 기준이 적용됨.

주소와 포인터 차이

주소 : 변수에 할당된 메모리 저장 공간의 시작 주소 값 자체

포인터 : 그 값을 저장하는 또 다른 메모리 공간.

따라서 특정 변수의 주소 값은 바뀌지 않지만, 포인터에 다른 주소를 대입해 그 값을 바꿀 수 있음.

주소는 상수, 포인터는 변수라고 여기기.

주소도 포인터처럼 간접 참조 연산자를 쓸 수 있지만, 상수이므로 대입 연산자 왼쪽에 올 수 없음.

주소와 포인터의 크기

포인터의 크기는 저장할 주소의 크기에 따라 결정, 크기가 클수록 더 넓은 범위의 메모리 사용.

모든 주소와 포인터는 가리키는 자료형에 관계가 없이 크기가 같다.

9-5 직접 해보는 손코딩

포인터의 대입 규칙

규칙1. 포인터는 가리키는 변수의 형태가 같을 때만 대입해야 함.

9-6 직접 해보는 손코딩

가리키는 자료형이 다른 포인터를 대입 연산하면 컴파일러에서 경고 메시지를 띄운다는데...

음.....??

규칙2. 형 변환을 사용한 포인터의 대입은 언제나 가능.

포인터가 가리키는 자료형이 다른 경우라도 형 변환 연산자를 사용하면 대입할 수 있음.

물론 대입한 후에 포인터를 통한 사용에 문제가 없어야 합니다.

double a = 3.4l
double *pd = &a;
int *pi;
pi = (int *)pd;

여기서 pi에 간접 참조 연산을 수행하면 변수 a의 일부를 int형 변수처럼 사용할 수 있음.

포인터를 사용하는 이유

포인터를 사용하려면 추가적인 변수 선언이 필요하고 주소 연산, 간접 참조 연산 등 각종 연산을 수행해야 함.
그러니 포인터를 일부러 즐겨 사용할 필요는 없음.

그러나 임베디드 프로그래밍을 할 때 메모리에 직접 접근하는 경우나 동적 할당한 메모리를 사용하는 경우에는 포인터가 반드시 필요함.

두 변수의 값을 바꾸며 포인트 이해하기

두 변수의 값을 바꾸는 함수를 통해 포인터의 필요성을 확인

9-7 직접 해보는 손코딩

포인터 없이 두 변수의 값을 바꾸는 함수는 불가능한가?

9-8 직접 해보는 손코딩

함수 안에서 선언된 변수명은 사용 범위가 함수 내부로 제한.

따라서 main 함수에 있는 변수 a, b는 변수는 다른 함수인 swap 함수에서 그 이름을 사용할 수 없음.

좀 더 정확히 설명하자만 변수가 선언된 시점부터 선언된 블록 끝까지로 제한됨.

9-9 직접 해보는 손코딩

main 함수의 변수 a, b의 값이 복사되어 15행의 매개변수 x, y에 저장됨.

결국 swap 함수 안에서는 a, b의 복사본을 바꾸므로 main 함수의 a, b의 값은 변함이 없게 됨.

swap 함수에서 매개변수 이름을 a, b로 사용해도 결과는 같음.

이름이 같아도 함수가 다르면 메모리에 별도의 저장 공간을 확보하므로 전혀 다른 변수로 사용됨.

swap 함수에서 바꾼 값을 main 함수로 반환하는 방법도, 함수는 오직 하나의 값만을 반환할 수 있으므로 한 번의 호출을 통해 두 변수의 값을 바꾸는 것은 불가능.


확인 문제

1. 다음 코드를 참고해 보기에서 상수와 변수를 구분하세요.

① 변수
② 상수
③ 변수
④ 변수
⑤ 상수

2. 주소 값의 크기가 4바이트일 때, sizeof 연산의 결괏값이 가장 큰 것을 고르세요.

(포인터 : 가르키는 변수의 시작 주소 값 : 둘 다 4

*포인터 : 가르키는 변수를 의미 : 1 / 8)

3. 다음 코드의 실행결과를 적으세요.

20, 10


커버 이미지

 

'C' 카테고리의 다른 글

13기 혼공학습단 회고록  (0) 2025.02.23
혼공C 5주차  (0) 2025.02.19
혼공C 4주차  (0) 2025.02.11
혼공C 3주차  (0) 2025.02.11
혼공C 2주차  (0) 2025.01.20