51
C 언언언 언언언 (1) 언언언언 언언 "언언언언언 언언언언" NHN NEXT 언언언 언언언언 언 언언언언언언 언언언 언언언 언언언 .

포인터의 기초(1)

Embed Size (px)

DESCRIPTION

C언어 포인터의 기초 첫번째 슬라이드입니다.

Citation preview

Page 1: 포인터의 기초(1)

C 언어와 포인터 (1)

포인터의 기초

"완전학습을 지향하는" NHN NEXT 정호영

나눔고딕 및 나눔고딕코딩 글꼴을 설치해 주세요 .

Page 2: 포인터의 기초(1)

쉽게

씌어진

창밖에

밤비가

속살거려

육첩방은

남의

나라

.시인이란

슬픈

천명인

알면서도

줄 시를

적어볼까

.

땀내와

사랑내

포근히

품긴

보내주신

학비 봉투를

받아

대학

노―

트를 끼고

늙은

교수의

강의 들으러

간다

.

생각해보면

어린

동무를

하나,

둘,

죄다

잃어버리고

나는

무얼

바라

나는

다만

,

홀로

침전하는

것일까

?

인생은

살기

어렵다는데

시가

이렇게

쉽게

씌어지는

것은

부끄러운

일이다

.

육첩방은

남의

나라

창밖에

밤비가

속살거리는데

등불을

밝혀

어둠을

조금

내몰고

시대처럼

아침을

기다리는

최후의

.

나는

나에게

적은

손을

내밀어

눈물과

위안으로

잡는

최초의

악수

.

Page 3: 포인터의 기초(1)

쉽게 씌어진 C창밖에 밤비가 속살거려육첩방은 남의 나라 .

C 인이란 슬픈 천명인 줄 알면서도한 줄 C 를 적어볼까 .

땀내와 사랑내 포근히 품긴보내주신 학비 봉투를 받아

대학 노―트를 끼고늙은 교수의 강의 들으러 간다 .

생각해보면 어린 때 동무를하나 , 둘 , 죄다 잃어버리고

나는 무얼 바라나는 다만 , 홀로 침전하는 것일까 ?

인생은 살기 어렵다는데C 가 이렇게 쉽게 씌어지는 것은부끄러운 일이다 .

육첩방은 남의 나라창밖에 밤비가 속살거리는데

등불을 밝혀 어둠을 조금 내몰고C 대처럼 올 아침을 기다리는 최후의 나 .

나는 나에게 적은 손을 내밀어 눈물과 위안으로 잡는 최초의 악수 .

Page 4: 포인터의 기초(1)

많은 초보들이 독학으로 C 언어를 배우는 과정

1. C 언어 책을 삽니다 .2. 책을 펼치고 열심히 공부합니다 .3. 포인터가 나옵니다 .4. 책을 덮습니다 .5. n 개월 휴식6. 1 번 또는 2 번으로 갑니다 .

Page 5: 포인터의 기초(1)

이 슬라이드 목표는여러분이 포인터에 대한 작은 깨달음을 얻는 것입니다 .

그리고 진실과 다른 내용이 더러 나옵니다 .

Page 6: 포인터의 기초(1)

기초 지식

Page 7: 포인터의 기초(1)

비트와 바이트

비트 : 1 또는 0 을 저장할 수 있는 공간

바이트 : 1 비트 8 개의 집합0000 0000 ~ 1111 1111

Page 8: 포인터의 기초(1)

예제 1)1 바이트로 표시할 수 있는 범위를 10 진수로 나타내면 ?

예제 2)1 바이트로 표시할 수 있는 범위를 16 진수로 나타내면 ?

Page 9: 포인터의 기초(1)

예제 1)1 바이트로 표시할 수 있는 범위를 10 진수로 나타내면 ?

0 ~ 255 ( -128 ~ 127 도 정답 )

예제 2)1 바이트로 표시할 수 있는 범위를 16 진수로 나타내면 ?

00 ~ FF

Page 10: 포인터의 기초(1)

예제 3) 다음 16 진수 덧셈을 해 봅시다 .

0 + 4 = 4 + 4 = 8 + 4 = C + 4 = C4 + 1C =

Page 11: 포인터의 기초(1)

예제 3) 다음 16 진수 덧셈을 해 봅시다 . 0 + 4 = 4 4 + 4 = 8 8 + 4 = C C + 4 = 10 C4 + 1C = E0

16 진수 0x4, 0x8, 0xC, 0x10 은 각각 4, 8, 12, 16 에 해당되는 숫자입니다 . 자주 나오니 기억합시다 .

Page 12: 포인터의 기초(1)

잠깐 메모리에 대해 알아보고 , & 연산자도 알아 봅시다 _

Page 13: 포인터의 기초(1)

메모리

컴퓨터의 메모리는 연속적인 선형 저장공간입니다 .

각 바이트마다 고유한 주소를 가집니다 .

(32 비트 PC 에서 )

가장 앞 주소 : 0000 0000

가장 뒤 주소 : FFFF FFFF

...

0000 0000

FFFF FFFF

0000 0001

FFFF FFFD

Page 14: 포인터의 기초(1)

OS 는 메 모 리의 일정 한 주소 를 묶 어 영 역 으로 만들었습니다 .각 영역마다 정해진 역할이 있습니다 .

어떤 게임에서 그린벨트 , 거주 구역 , 공업지구 등으로 나눈 거랑 비슷합니다 .

중 3 성적을 말아먹은 게임

Page 15: 포인터의 기초(1)

메모리 영역은 크게 코드 , 데이터 , 스택 , 힙으로 나뉩니다 .각각의 역할은 조금 나중에…

물론 이 그림은 추상화입니다 .

Page 16: 포인터의 기초(1)

예제 3)메모리 주소를 표현하기 위해서 필요한 최소한의 크기는 ?

...

0000 0000

FFFF FFFF

0000 0001

FFFF FFFD

Page 17: 포인터의 기초(1)

예제 3)메모리 주소를 표현하기 위해서 필요한 최소한의 크기는 ?

4 바이트

# unsigned int = 4 바이트이므로 주소를 저장할 수 있다 .

...

0000 0000

FFFF FFFF

0000 0001

FFFF FFFD

Page 18: 포인터의 기초(1)

* 참고옛날 16 비트 IBM DOS 시절에int 는 2byte(16bit) 지만 메모리 주소는 20bit 여서unsigned int 로 주소를 표현할 수 없었습니다 .

...

0 0000

3 FFFF

0 0001

3 FFFD

Page 19: 포인터의 기초(1)

변수

1. 메모리의 어딘가에 필요한 크기만큼 자리를 잡고2. 이름을 붙여줌3. 적절한 값을 넣을 수 있음

int n = 10; //4 바이트char a = 'x'; //1 바이트double d = 5.23; //8 바이트

Page 20: 포인터의 기초(1)

예제 4)

다음 문장을 보고 찍어 보세요 .

1. 위 문장에 필요한 공간은 ?

2. 위 변수의 이름은 ?

3. 위 변수의 타입은 ?

double doo[] = { 3.14, 1.414, 1.717 };

Page 21: 포인터의 기초(1)

예제 4)

다음 문장을 보고 찍어 보세요 .

1. 위 문장에 필요한 공간은 ? 24 바이트

2. 위 변수의 이름은 ? doo

3. 위 변수의 타입은 ? 더블의 배열 타입 (?)

double doo[] = { 3.14, 1.414, 1.717 };

Page 22: 포인터의 기초(1)

변수의 종류

전역 변수 (global variable)

정적 변수 (static variable)

지역 변수 (local variable) = 자동변수 (auto variable)

Page 23: 포인터의 기초(1)

단항 연산자 &단항 연산자 (unary operator) & 는 주소 연산자입니다 .변수의 주소를 알고 싶을 때 사용합니다 .

printf 에서 주소를 출력할 때는 %p 입니다 .

Page 24: 포인터의 기초(1)

변수의 주소 알아보기

전역변수의 주소지역변수의 주소정적변수의 주소포인터 ?함수 ?

결과주소를내림차순으로 정 렬해 봅시다 .

Page 25: 포인터의 기초(1)

변수가 위치하는 영역의 이름

종류 위치 설명

함수 코드 소스코드 , 리터럴이 위치

전역 및 정적변수 데이터 데이터 영역

포인터 ( 동적 할당 ) 힙 동적 할당 영역

지역변수 스택 함수 내부 / 임시저장용

Page 26: 포인터의 기초(1)

여기부터 진짜로 포인터 이 야기 _

Page 27: 포인터의 기초(1)

포인터 (Pointer)

포인터는 주소를 저장하는 특이 (特異 ) 한 자 료형입니다 .그리고 저장한 주소에 가서 값을 읽어옵니다 .그게 전부예요 .

Page 28: 포인터의 기초(1)

포인터 (Pointer)

포인터는 주소를 저장하는 특별한 자 료형입니다 .그리고 저장한 주소에 가서 값을 읽어옵니다 .그게 전부예요 .

거짓말 .한 3% 정도 됩니다 .

Page 29: 포인터의 기초(1)

포인터 (Pointer)

주소를 저장한다구요 ? 그럼 , 이게 다 뭔가요 ?

놀라지 말고 차근차근 하나 씩 알아 봅시다 :D

int *ptr;char *ptr;void *ptr;int **pptr;int *ptr[5];int (*ptr)[3];int (*foo)(double a);

Page 30: 포인터의 기초(1)

배우기 전에 그 림을 그리기 위한 규칙을 배웁시다 .그림으로 그리면 조금 이해가 잘 됩니다 .제가 고심해서 만들……

포인터 char intdouble

struct

Page 31: 포인터의 기초(1)

일반 변수의 선언 및 초기화는 아래처럼 그 릴 수 있습니다 .

int a = 20;

아래의 희미한 건 실제 저장되는 메모리의 시작주소입니다 .

20a

0x080481AC

Page 32: 포인터의 기초(1)

포인터 변수는 주소를 저장하는 변수입니다 .

형식은 타입 * 변수명 이 됩니다 .

변수 선언할 때 * 는 어떤 변수가 포인터라는 것을 나타 냅니다 .

아래 선언 코드는 "ptr 은 int 의 포인터다 " 라는 뜻입니다 .

ptr

int *ptr;

Page 33: 포인터의 기초(1)

포인터에는 주소값이 저장 됩니다 .

이미 & 연산자를 이용해서 주소를 알아올 수 있으므로 사용해 봅시다 .

ptr

int a = 20;int *ptr;ptr = &a;

20a

0x080481AC

0x080481AC

Page 34: 포인터의 기초(1)

동그라 미라서 칸이 모자 랍니다 .

어차피 a 의 주소를 가 르킨 거니까 그 냥 화살표로 연 결해 봅시다 .

a 의 주소도 귀찮으니까 지 웁니다 .

ptr

int a = 20;int *ptr;ptr = &a;

20a

Page 35: 포인터의 기초(1)

포인터가 가 르키는 변수를 특별히 포인 티라고 합시다 .

다른 곳에서는 그렇게 안 부 르는데 미국의 S 대학 자 료에서 발견한 멋진 이름입니다 .

위 그 림의 해석" 포인터 변수 ptr 의 포인티는 int a 이고 20 이 저장되어 있다 ."

ptr

20a

Page 36: 포인터의 기초(1)

포인터 규칙 1.

포인터와 포인티는 같은 타입이어 야 한다 .

Page 37: 포인터의 기초(1)

포인터에는 아무 주소나 들어 갈 수 있을까요 ? 아닙니다 .

포인터 규칙 1.

포인터와 포인티는 같은 타입이어 야 한다 .

ptr

20a

ptr 은 int 의 포인터라는 걸 그림만 봐도 알 수 있어요 !

Page 38: 포인터의 기초(1)

포인터에는 아무 변수의 주소나 들어 갈 수 있을까요 ? 아닙니다 .

포인터 규칙 1.

포인터와 포인티는 같은 타입이어 야 한다 .

int a = 20;int *ptr;ptr = &a;

Page 39: 포인터의 기초(1)

문 ) 다음 코드에 문제가 없는지 그 림으로 확인해 보세요 .

double *ptr1, *ptr2, dnum; dnum = 3.14;ptr1 = &a;ptr2 = ptr1;

Page 40: 포인터의 기초(1)

문 ) 다음 코드에 문제가 없는지 그 림으로 확인해 보세요 .

double *ptr1, *ptr2, dnum; dnum = 3.14;ptr1 = &a;ptr2 = ptr1;

Page 41: 포인터의 기초(1)

문 ) 다음 그 림을 코드로 나타내 보세요 .

ptr1

h

c0

i

c1

ptr2

Page 42: 포인터의 기초(1)

문 ) 다음 그 림을 코드로 나타내 보세요 .

ptr1

h

c0

i

c1

ptr2

char c0 = 'h';char c1 = 'i';char *ptr1 = &c0;char *ptr2 = &c1;

Page 43: 포인터의 기초(1)

포인터 규칙 2.

포인터 변수는 반드시 초기 화 후에 사용해 야 한다 .

사실 그 냥 변수도 그렇습니다 .

Page 44: 포인터의 기초(1)

포인터의 사용을 위해서는 * 연산자를 사용합니다 .

선언이 아 닌 곳에서 * 를 붙여서 포인 티의 값을 읽거나 쓸 수 있습니다 .

int a = 20;int *ptr = &a;printf("%d\n", *ptr) //*ptr 이 int 라는 걸 알겠죠 ?

ptr

20a

ptr 의 포인티는 a 이므로 *ptr 을 읽으면 20 이 나옵니다 .

Page 45: 포인터의 기초(1)

포인터를 사용하려면 * 연산자를 사용합니다 .

선언이 아 닌 곳에서 * 를 붙이면 포인티의 값을 읽거나 쓸 수 있습니다 .

int a = 20;int *ptr = &a;printf("%d\n", *ptr) //20*ptr = 50;printf("%d\n", *ptr) //50printf("%d\n", a) //?

ptr

20 50a

*ptr 에 50 을 넣으면 자신이 아니라 포인 티가 50 이 됩니다 .Make

sense?Reasonable

?

LV?? 스마트 데이터 조봉수 팀장님

Page 46: 포인터의 기초(1)

포인터를 사용한다라는 건 결국 * 을 사용한다는 것입니다 .

그런데 초기 화를 해 주지 않으면 포인 티가 존재하지 않습니다 .

아래 코드를 실 행하면 어 떻게 될까요 ? 그림으로 그리면 ?

int *ptr;*ptr = 50;printf("%d\n", *ptr) //?

ptr

Page 47: 포인터의 기초(1)

초기화를 해 주지 않은 포인터는 절대 사용하면 안 됩니다 .

그래서 초기 화하지 않은 포인터는 아 래처럼 그 립니다 .

ptr

LV.99 가비지 포인터

< 엄청난 버그를 양산 >

Page 48: 포인터의 기초(1)

다음 코드의 문제는 무 엇인지 실행도 해 보고그림으로 그려 봅시다 .

* 참고로 맥에서 GCC 로 컴 파일하면 잘 실행됩니다 .

main() { int *ptr; foo(ptr);}

void foo(int *p) { *p = 100; printf(“%d\n”, *p);}

Page 49: 포인터의 기초(1)

포인터 규칙 3.

void* 는 읽을 수 없다 .

사실 그 냥 변수도 그렇습니다 .

Page 50: 포인터의 기초(1)

void * 란 ? 어떤 타입의 주소도 닮을 수 있는 만 능 그릇int 도 double 도 char 도 누구라도 포인 티가 될 수 있습니다 !!

두 줄 동그라 미로 그리도 록 하겠습니다 .

ptr

Page 51: 포인터의 기초(1)

To be continued…