쉽게 풀어쓴 C언어 Express 제14장 포인터 활용 C Express.

Slides:



Advertisements
Similar presentations
Chapter 12. 배열. 배열  동일한 항목들이 동일한 크기로 연속적으로 메모리에 저장되는 구조  동일한 자료 유형이 여러 개 필요한 경우에 이용할 수 있는 자료 구조.
Advertisements

1 08 배열. 한국대학교 객체지향연구소 2 C 로 배우는 프로그래밍 기초 2 nd Edition 배열  동일한 자료유형의 여러 변수를 일괄 선언  연속적인 항목들이 동일한 크기로 메모리에 저장되는 구조  동일한 자료 유형이 여러 개 필요한 경우에 이용할 수 있는.
1. 2 차원 배열  배열은 동일한 데이터 유형으로 여러 개의 변수를 사용할 경우 같은 이 름으로 지정하여 간편하게 사용할 수 있도록 하는 것으로서 앞에서 1 차원 배열을 공부하였습니다.  2 차원 배열은 바둑판을 생각하면 되며, 1 차원 배열에서 사용하는 첨자를 2.
구조체, 포인터 활용 컴퓨터시뮬레이션학과 2014년 봄학기 담당교수 : 이형원 E304호,
포인터란? 사전적 의미로써 지시자 혹은 가리키는 것으로 풀이할 수 있으나, C프로그래밍 언어에서는 메모리의 주소를 저장하는 변수이다. 포인터 자체가 하나의 변수이기 때문에 포인터도 메모리 내에서 선언이 되며 일반 상수를 저장하는 변수가 아닌 주소값을 저장하는 변수라는 점에서.
ㅎㅎ 구조체 구조체 사용하기 함수 매개변수로서의 구조체 구조체 포인터와 레퍼런스 구조체 배열.
슬라이드 1~21까지는 각자 복습! 슬라이드 22부터는 수업시간에 복습
쉽게 풀어쓴 C언어 Express 제11장 포인터 C Express.
쉽게 풀어쓴 C언어 Express 제11장 포인터 C Express Slide 1 (of 27)
제 9 장 포인터.
쉽게 풀어쓴 C언어 Express 제11장 포인터 C Express.
2장. 프로그램의 기본 구성. 2장. 프로그램의 기본 구성 2-1"Hello, World!" 들여다 보기 /* Hello.c */ #include int main(void) { printf("Hello, World! \n"); return 0;
쉽게 풀어쓴 C언어 Express 제11장 포인터 C Express.
쉽게 풀어쓴 C언어 Express 제11장 포인터 C Express.
9장. C 언어의 핵심! 함수. 9장. C 언어의 핵심! 함수 9-1 함수의 정의와 선언 main 함수 다시 보기 : 함수의 기본 형태 { } 그림 9-1.
#include <stdio.h> int main(void) { float radius; // 원의 반지름
제 9 장 구조체와 공용체.
Report #2 - Solution 문제 #1: 다음과 같이 프로그램을 작성하라.
-Part2- 제3장 포인터란 무엇인가.
C 11장. 포인터의 활용 #include <stdio.h> int main(void) { int num;
윤 홍 란 포인터 윤 홍 란
C 8장. 포인터 #include <stdio.h> int main(void) { int num;
자료 구조: Chapter 3 (2)구조체, 포인터
3장. 변수와 연산자. 3장. 변수와 연산자 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, / 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, /
개정판 누구나 즐기는 C언어 콘서트 제9장 포인터 출처: pixabay.
5장 배열 작성자 : 변재현.
누구나 즐기는 C언어 콘서트 제8장 배열.
C 프로그래밍.
11장. 포인터 01_ 포인터의 기본 02_ 포인터와 Const.
포인터 활용 포인터 활용.
프로그래밍실습 제 11 강.
쉽게 풀어쓴 C언어 Express 제14장 포인터 활용 C Express.
8장 함수 함수의 필요성 라이브러리 함수와 사용자 정의 함수 함수의 정의, 원형, 호출 배열을 함수 인자로 전달 재귀호출.
쉽게 풀어쓴 C언어 Express 제14장 포인터 활용 C Express.
컴퓨터 프로그래밍 기초 #02 : printf(), scanf()
쉽게 풀어쓴 C언어 Express 제10장 배열 C Express Slide 1 (of 32)
제8장 배열 1부 8.1 배열 8.2 배열의 초기화 8.3 배열의 응용 8.4 정렬과 탐색 8.5 다차원 배열.
Tail-recursive Function, High-order Function
14장. 포인터와 함수에 대한 이해.
11장. 1차원 배열.
C 8장. 포인터 #include <stdio.h> int main(void) { int num;
쉽게 풀어쓴 C언어 Express 제3장 C프로그램 구성요소 C Express.
JA A V W. 03.
사용자 함수 사용하기 함수 함수 정의 프로그램에서 특정한 기능을 수행하도록 만든 하나의 단위 작업
어서와 C언어는 처음이지 제14장.
13. 포인터와 배열! 함께 이해하기 IT응용시스템공학과 김 형 진 교수.
3장 상수 변수 기본 자료형 키워드와 식별자 상수와 변수 기본 자료형 형변환 자료형의 재정의.
쉽게 풀어쓴 C언어 Express 제14장 포인터 활용 C Express Slide 1 (of 22)
19. 함수 포인터와 void 포인터.
3장. 변수와 연산자 교안 : 전자정보통신 홈페이지 / 커뮤니티/ 학술세미나
Chapter6 : JVM과 메모리 6.1 JVM의 구조와 메모리 모델 6.2 프로그램 실행과 메모리 6.3 객체생성과 메모리
컴퓨터 프로그래밍 기초 - 10th : 포인터 및 구조체 -
컴퓨터 프로그래밍 기초 - 5th : 조건문(if, else if, else, switch-case) -
김선균 컴퓨터 프로그래밍 기초 - 7th : 함수 - 김선균
컴퓨터 프로그래밍 기초 - 8th : 함수와 변수 / 배열 -
8주차: Strings, Arrays and Pointers
5강. 배열 배열이란? 배열의 문법 변수와 같이 이해하는 배열의 메모리 구조의 이해 레퍼런스의 이해 다차원 배열
9장. C 언어의 핵심! 함수. 9장. C 언어의 핵심! 함수 9-1 함수의 정의와 선언 main 함수 다시 보기 : 함수의 기본 형태 { } 그림 9-1.
-Part1- 제7장 반복문이란 무엇인가.
^^ Computer Programming 2 dmpr.cnu.ac.kr/~daygax.
함수(Function) ◈ 함수의 개념 및 사용 이유 ◈ 함수 정의, 호출 및 선언 ◈ 지역변수와 전역변수 ◈ return 문
쉽게 풀어쓴 C언어 Express 제6장 조건문 C Express.
컴퓨터 프로그래밍 기초 - 9th : 배열 / 포인터 -
Summary of Pointers and Arrays
어서와 C언어는 처음이지 제21장.
개정판 누구나 즐기는 C언어 콘서트 제13장 동적 메모리 출처: pixabay.
13. 포인터와 배열! 함께 이해하기.
개정판 누구나 즐기는 C언어 콘서트 제14장 전처리와 분할 컴파일리 출처: pixabay.
Pointers summary.
2019 2학기 9장 배열과 포인터 1. 주소, 주소연산자(&) 2. 포인터, 역참조연산자(*) 3. 배열과 포인터.
Presentation transcript:

쉽게 풀어쓴 C언어 Express 제14장 포인터 활용 C Express

이중 포인터 이중 포인터(double pointer) : 포인터를 가리키는 포인터 int i = 10; // i는 int형 변수 int *p = &i; // p는 i를 가리키는 포인터 int **q = &p; // q는 포인터 p를 가리키는 이중 포인터

이중 포인터 이중 포인터의 해석

이중 포인터 p i q *q // 이중 포인터 프로그램 #include <stdio.h> int main(void) 이중포인터 100 200 300 i // 이중 포인터 프로그램 #include <stdio.h> int main(void) { int i = 100; int *p = &i; int **q = &p; *p = 200; printf("i=%d *p=%d **q=%d \n", i, *p, **q); **q = 300; return 0; } i=200 *p=200 **q=200 i=300 *p=300 **q=300

예제 #2 #include <stdio.h> void set_pointer(char **q); char *proverb="All that glisters is not gold."; int main(void) { char *p="zzz"; set_pointer(&p); printf("%s \n", p); return 0; } void set_pointer(char **q) *q = proverb; 포인터 p의 값을 함수에서 변경하려면 주소를 보내야 한다. All that glisters is not gold.

중간 점검 double형 포인터를 가리키는 이중 포인터 dp를 선언하여 보자. char c; char *p; char **dp; p = &c; dp =&p;와 같이 정의되었을 때 **dp은 무엇을 가리키는가?

포인터 배열 포인터 배열(array of pointers): 포인터를 모아서 배열로 만든것

정수형 포인터 배열 int a = 10, b = 20, c = 30, d = 40, e = 50; int *pa[5] = { &a, &b, &c, &d, &e };

2차원 배열에 문자열을 저장 char fruits[4 ][10] = { "apple", "blueberry", "orange", “melon" };

문자형 포인터 배열 char *fruits[ ] = { "apple", "blueberry", "orange", “melon" };

문자열 배열 // 문자열 배열 #include <stdio.h> int main(void) { int i, n; char *fruits[ ] = { "apple", "blueberry", "orange", "melon" }; n = sizeof(fruits)/sizeof(fruits[0]); // 배열 원소 개수 계산 for(i = 0; i < n; i++) printf("%s \n", fruits[i]); return 0; } apple blueberry orange melon

중간 점검 double형의 포인터 10개를 가지는 배열을 정의하여 보자. 래그드 배열이 일반적인 2차원 배열보다 좋은 점은 무엇인가?

배열 포인터 배열 포인터(a pointer to an array)는 배열을 가리키는 포인터

예제 #include <stdio.h> int main(void) { int a[5] = { 1, 2, 3, 4, 5 }; int (*pa)[5]; int i; pa = &a; for(i=0 ; i<5 ; i++) printf("%d \n", (*pa)[i]); return 0; } 배열 포인터 1 2 3 4 5

함수 포인터 함수 포인터(function pointer): 함수를 가리키는 포인터 int (*pf)(int, int);

함수 포인터의 해석

함수 포인터의 사용 int sub(int, int); // 함수 원형 정의 int (*pf)(int, int); // 함수 포인터 정의 ... pf = sub; // 함수의 이름을 함수 포인터에 대입 result = pf( 10, 20); // 함수 포인터를 통하여 함수 호출

fp1.c // 함수 포인터 #include <stdio.h> // 함수 원형 정의 int add(int, int); int sub(int, int); int main(void) { int result; int (*pf)(int, int); // 함수 포인터 정의 pf = add; // 함수 포인터에 함수 add()의 주소 대입 result = pf(10, 20); // 함수 포인터를 통한 함수 add() 호출 printf("10+20은 %d\n", result); pf = sub; // 함수 포인터에 함수 sub()의 주소 대입 result = pf(10, 20); // 함수 포인터를 통한 함수 sub() 호출 printf("10-20은 %d\n", result); return 0; }

fp1.c int add(int x, int y) { return x+y; } int sub(int x, int y) 10+20은 30 10-20은 -10

함수 포인터의 배열 int (*pf[5]) (int, int);

함수 포인터의 배열 int (*pf[5]) (int, int);

함수 포인터 배열 // 함수 포인터 배열 #include <stdio.h> // 함수 원형 정의 void menu(void); int add(int x, int y); int sub(int x, int y); int mul(int x, int y); int div(int x, int y); void menu(void) { printf("=====================\n"); printf("0. 덧셈\n"); printf("1. 뺄셈\n"); printf("2. 곱셈\n"); printf("3. 나눗셈\n"); printf("4. 종료\n"); }

함수 포인터 배열 int main(void) { int choice, result, x, y; 함수 포인터 배열 // 함수 포인터 배열을 선언하고 초기화한다. int (*pf[4])(int, int) = { add, sub, mul, div }; while(1) menu(); printf("메뉴를 선택하시오:"); scanf("%d", &choice); if( choice < 0 || choice >=4 ) break; printf("2개의 정수를 입력하시오:"); scanf("%d %d", &x, &y); result = pf[choice](x, y); // 함수 포인터를 이용한 함수 호출 printf("연산 결과 = %d\n",result); } return 0; 함수 포인터 배열 선언

함수 포인터 배열 int add(int x, int y) { return x + y; } int sub(int x, int y) return x - y; int mul(int x, int y) return x * y; int div(int x, int y) return x / y; ===================== 0. 덧셈 1. 뺄셈 2. 곱셈 3. 나눗셈 4. 종료 메뉴를 선택하시오:2 2개의 정수를 입력하시오:10 20 연산 결과 = 200 메뉴를 선택하시오:

함수 인수로서의 함수 포인터 함수 포인터도 인수로 전달이 가능하다.

예제 다음과 같은 수식을 계산하는 프로그램을 작성하여 보자. 여기서 f(k)는 다음과 같은 함수들이 될 수 있다.

예제 #include <stdio.h> #include <math.h> double f1(double k); double f2(double k); double formula(double (*pf)(double), int n); int main(void) { printf("%f\n", formula(f1, 10)); printf("%f\n", formula(f2, 10)); } double formula(double (*pf)(double), int n) int i; double sum = 0.0; for(i = 1; i < n; i++) sum += pf(i) * pf(i) + pf(i) + 1; return sum;

예제 double f1(double k) { return 1.0 / k; } double f2(double k) return cos(k); 13.368736 12.716152

중간 점검 int 값을 반환하고 double 값을 인수로 받는 함수의 포인터 pf를 선언하여 보자. 1번의 함수 포인터를 통하여 3.0을 인수로 하여 함수를 호출하는 문장을 작성하라.

다차원 배열과 포인터 2차원 배열 int m[3][3] 1행->2행->3행->...순으로 메모리에 저장(행우선 방법)

2차원 배열과 포인터 배열 이름 m은 &m[0][0] m[0]는 1행의 시작 주소 m[1]은 2행의 시작 주소 ...

2차원 배열의 해석

multi_array.c #include <stdio.h> int main(void) { printf("m = %p\n", m); printf("m[0] = %p\n", m[0]); printf("m[1] = %p\n", m[1]); printf("m[2] = %p\n", m[2]); printf("&m[0][0] = %p\n", &m[0][0]); printf("&m[1][0] = %p\n", &m[1][0]); printf("&m[2][0] = %p\n", &m[2][0]); return 0; } m m[0] m[1] m[2] 10 20 30 40 50 60 70 80 90 m[0][0] m[0][1] m[0][2] m[1][0] m[1][1] m[1][2] m[2][0] m[2][1] m[2][2] m = 1245020 m[0] = 1245020 m[1] = 1245032 m[2] = 1245044 &m[0][0] = 1245020 &m[1][0] = 1245032 &m[2][0] = 1245044

2차원 배열과 포인터 연산 2차원 배열 m[][]에서 m에 1을 더하거나 빼면 어떤 의미일까?

포인터를 이용한 배열 원소 방문 행의 평균을 구하는 경우 double get_row_avg(int m[][COLS], int r) { int *p, *endp; double sum = 0.0; p = &m[r][0]; endp = &m[r][COLS]; while( p < endp ) sum += *p++; sum /= COLS; return sum; }

포인터를 이용한 배열 원소 방문 전체 원소의 평균을 구하는 경우 double get_total_avg(int m[][COLS]) { int *p, *endp; double sum = 0.0; p = &m[0][0]; endp = &m[ROWS-1][COLS]; while( p < endp ) sum += *p++; sum /= ROWS * COLS; return sum; }

중간 점검 m[10][10]에서 m[0]의 의미는 무엇인가? m[10][10]에서 (m+1)의 의미는 무엇인가?

const 포인터 const를 붙이는 위치에 따라서 의미가 달라진다.

예제 #include <stdio.h> int main(void) { char s[] = "Barking dogs seldom bite."; char t[] = "A bad workman blames his tools"; const char * p=s; char * const q=s; //p[3] = 'a'; p = t; q[3] = 'a‘; //q = t; return 0; } p가 가리키는 곳의 내용을 변경할 수 없다. 하지만 p는 변경이 가능하다. q가 가리키는 곳의 내용은 변경할 수 있다. 하지만 q는 변경이 불가능하다.

volatile 포인터 volatile은 다른 프로세스나 스레드가 값을 항상 변경할 수 있으니 값을 사용할 때마다 다시 메모리에서 읽으라는 것을 의미

void 포인터 순수하게 메모리의 주소만 가지고 있는 포인터 가리키는 대상물은 아직 정해지지 않음 (예) void *vp; 다음과 같은 연산은 모두 오류이다. *vp; // 오류 *(int *)vp; // void형 포인터를 int형 포인터로 변환한다. vp++; // 오류 vp--; // 오류

vp.c #include <stdio.h> int main(void) { int a[] = { 10, 20, 30, 40, 50 }; void *vp; vp = a; // 가능 vp = &a[2]; // 가능 //*vp = 35; // 오류 //vp++; // 오류 *(int *)vp = 35; // 가능 return 0; }

중간 점검 void형 포인터 vp를 int형 포인터 ip로 형변환하는 문장을 작성하라.

main() 함수의 인수 지금까지의 main() 함수 형태 외부로부터 입력을 받는 main() 함수 형태 int main(void) { .. } int main(int argc, char *argv[]) { .. }

인수 전달 방법 C: \cprogram> mycopy src dst

main_arg.c c:\cprogram\mainarg\Debug>mainarg src dst #include <stdio.h> int main(int argc, char *argv[]) { int i = 0; for(i = 0;i < argc; i++) printf("명령어 라인에서 %d번째 문자열 = %s\n", i, argv[i]); return 0; } c:\cprogram\mainarg\Debug>mainarg src dst 명령어 라인에서 0번째 문자열 = mainarg 명령어 라인에서 1번째 문자열 = src 명령어 라인에서 2번째 문자열 = dst c:\cprogram\mainarg\Debug>

비주얼 C++ 프로그램 인수 입력 방법 [프로젝트]->[main_arg.exe 속성] 선택

mile2km.c c:\cprogram\mainarg\Debug>mainarg 10 #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { double mile, km; if( argc != 2 ){ printf("사용 방법: mile2km 거리\n"); return 1; } mile = atof(argv[1]); km = 1.609 * mile; printf("입력된 거리는 %f km입니다. \n", km); return 0; c:\cprogram\mainarg\Debug>mainarg 10 입력된 거리는 16.090000 km입니다. c:\cprogram\mainarg\Debug>

중간 점검 C>main arg1 arg2 arg3와 같이 실행시킬 때 argv[0]가 가리키는 것은? C>main arg1 arg2 arg3와 같이 실행시킬 때 argc의 값은?

실습: 이분법으로 근 구하기 2차식의 경우에는 공식이 있지만 일반적인 n차식의 경우 공식이 존재하지 않는다. 이때 사용할 수 있는 방법이 이분법(bisection)이다

이분법 구간 [a, b]에서 근을 가지는 것이 확실하면 구간 [a, b]의 중점 m을 구하여 구간 [a, m]과 구간 [m, b]로 나눈다. 각각의 구간에서 다시 f(a)와 f(b)의 부호를 조사하여 근이 어떤 구간에 위치하는지를 결정한다. 다시 그 구간에 대하여 동일한 과정을 되풀이한다.

실행 결과 다음과 같은 함수에 대하여 근을 구한다. 함수 포인터를 받는 get_root()를 작성한다. double get_root(double (*fp)(double), double a, double b); a의 값을 입력하시오 -200 b의 값을 입력하시오 200 값은 -2.104950

예제 소스 #include<stdio.h> #include <math.h> #define ESP 0.001 double get_root(double (*f)(double), double a, double b); double func(double x) { return (x)*(x)*(x) + (x)*(x) + (x) + 7; } void main() double x0,x1; double r; printf("a의 값을 입력하시오"); scanf("%lf",&x0); printf("b의 값을 입력하시오"); scanf("%lf",&x1); r = get_root(func, x0, x1); printf("값은 %f\n", r); return 0;

예제 소스 double get_root(double (*f)(double), double x0, double x1) { float x2; int i = 1; double f1,f2,f0; do x2=(x0+x1)/2; f0=f(x0); f1=f(x1); f2=f(x2); if(f0*f2<0) x1=x2; else x0=x2; i++; } while(fabs(f2)>ESP); return x2; } 부호가 다르면 f2의 절대값이 무시할 만큼 작아지면, 즉 0에 가까워지면

도전문제 사용자로부터 함수를 입력받도록 프로그램을 수정할 수 있는가? 다항식의 최고차수는 3으로 제한하도록 하자.

Q & A