430 likes | 548 Views
2008 년 4 월 30 일. Happy Quiz Time. 1. 다음 프로그램의 빈 칸을 채우시오 #include <stdio.h> void value_swap(int a, int b); // swap 함수의원형 int main(void) { int num1, num2; printf(" 두숫자입력 : "); scanf("%d%d", &num1, &num2); printf("Before : %d %d <br>", num1, num2);
E N D
1. 다음 프로그램의 빈 칸을 채우시오 • #include <stdio.h> • void value_swap(int a, int b); // swap함수의원형 • int main(void) • { • int num1, num2; • printf("두숫자입력: "); • scanf("%d%d", &num1, &num2); • printf("Before : %d %d \n", num1, num2); • value_swap(num1, num2); // swap함수호출 • return 0; • } • void value_swap(int a, int b) • { • int temp; // 임시정수형변수선언 • ( ) • ( ) ( ) • printf("After : %d %d \n", a, b); • }
2. 다음 프로그램의 빈 칸을 채우시오 #include <stdio.h> int factorial(int n); int main(void) { int num; printf("Recursive Factorial \n"); printf("Input : "); scanf("%d", &num); printf("%d's factorial is %d \n", num, factorial(num)); return 0; } int factorial(int n) { if (n==1) return 1; return n * ( ); }
3. 다음 프로그램의 빈 칸을 채우시오#include <stdio.h>int main(void){ int max, min; int num[5]; int i; printf("Input five numbers \n");/* 5개의숫자를배열에입력*/ for (i=0; i<5; i++) scanf("%d“, ________);/* 최소값과최대값을추출*/ min = num[0]; max = num[0];/* 반복문을통해배열의각원소에접근, 최대/최소갱신*/ for (i=1; i<5; i++){ if ( ) max = num[i]; if (__________) min = num[i];} printf("최소: %d \n최대: %d \n", min, max); return 0;}
12-1포인터란 무엇인가? • 포인터와 포인터 변수 • 메모리의 주소 값을 저장하기 위한 변수 • "포인터"를 흔히 "포인터 변수"라 한다. • 주소 값과 포인터는 다른 것이다. int main(void) { char c='a'; int n=7; double d=3.14; . . . . . 그림 12-1
12-1포인터란 무엇인가? • 그림을 통한 포인터의 이해 • 컴퓨터의 주소 체계에 따라 크기가 결정 • 32비트 시스템 기반 : 4 바이트 그림 12-2
12-1포인터란 무엇인가? • 포인터의 타입과 선언 • 포인터 선언 시 사용되는 연산자 : * • A형 포인터(A*) : A형 변수의 주소 값을 저장 int main(void) { int *a;// a라는 이름의 int형 포인터 char *b;// b라는 이름의 char형 포인터 double *c;// c라는 이름의 double형 포인터 . . . . .
12-1포인터란 무엇인가? • 주소 관련 연산자(pointer1.c 참조) • & 연산자 : 변수의 주소 값 반환 • * 연산자 : 포인터가 가리키는 메모리 참조 int main(void) { int a=2005; int *pA=&a; printf(“%d”, a); //직접 접근 printf(“%d”, *pA); // 간접 접근 . . . . . 그림 12-3
/* pointer1.c */ #include <stdio.h> int main(void) { int a=2005; int* pA=&a; printf("pA : %d \n", pA); printf("&a : %d \n", &a); (*pA)++; //a++와 같은 의미를 지닌다. printf("a : %d \n", a); printf("*pA : %d \n", *pA); return 0; }
12-1포인터란 무엇인가? • 포인터에 다양한 타입이 존재하는 이유 • 포인터 타입은 참조할 메모리의 크기 정보를 제공 #include <stdio.h> int main(void) { int a=10; int *pA = &a; double e=3.14; double *pE=&e; printf(“%d %f”, *pA, *pE); return 0; }
12-2잘못된 포인터의 사용 • 사례 1 • 사례 2 int main(void) { int *pA; // pA는 쓰레기 값으로 초기화 됨 *pA=10; return 0; } int main(void) { int* pA=100; // 100이 어딘 줄 알고??? *pA=10; return 0; }
13-1 포인터와 배열의 관계 • 배열의 이름의 정체 • 배열 이름은 첫 번째 요소의 주소 값을 나타낸다. • pointer_array1.c 참조 int a[5]={0, 1, 2, 3, 4} 그림 13-1
13-1 포인터와 배열의 관계 /* pointer_array1.c */ #include <stdio.h> int main(void) { int a[5]={0, 1, 2, 3, 4}; printf("%d, %d \n", a[0], a[1]); printf("%d 번지 , %d 번지 \n", &a[0], &a[1]); printf("배열 이름 : %d \n", a); return 0; }
13-1 포인터와 배열의 관계 • 배열 이름과 포인터 비교 int main(void) { int a[5]={0, 1, 2, 3, 4}; int b=10; a=&b; //a는 상수이므로 오류, a가 변수였다면 OK! }
13-1 포인터와 배열의 관계 • 배열 이름의 타입 • 배열 이름도 포인터이므로 타입이 존재 • 배열 이름이 가리키는 배열 요소에 의해 결정 int arr1[10] int* double arr2[20] double*
13-1 포인터와 배열의 관계 • 배열 이름의 활용 • 배열 이름을 포인터처럼, 포인터를 배열 이름처럼 활용하는 것이 가능! /* pointer_array2.c */ #include <stdio.h> int main(void) { int arr[3]={0, 1, 2}; int *ptr; ptr=arr; printf("%d, %d, %d \n", ptr[0], ptr[1], ptr[2]); return 0; } 그림 13-2
13-2포인터 연산 • 포인터 연산이란? • 포인터가 지니는 값을 증가 혹은 감소시키는 연산을 의미 ptr1++; ptr1 += 3; --ptr1; ptr2=ptr1+2;
13-2포인터 연산 • 포인터 연산 • 포인터가 가리키는 대상의 자료형에 따라서 증가 및 감소되는 값이 차이를 지님 /* pointer_op.c */ #include <stdio.h> int main(void) { int* ptr1=0; // int* ptr1=NULL; 과 같은 문장 char* ptr2=0; // char* ptr2=NULL; 과 같은 문장 double* ptr3=0; // double* ptr3=NULL; 과 같은 문장 printf("%d 번지, %d 번지, %d 번지 \n", ptr1++, ptr2++, ptr3++); printf("%d 번지, %d 번지, %d 번지 \n", ptr1, ptr2, ptr3); return 0; }
13-2포인터 연산 • 포인터 연산을 통한 배열 요소의 접근 /* pointer_array3.c */ #include <stdio.h> int main(void) { int arr[5]={1, 2, 3, 4, 5}; int* pArr=arr; printf("%d \n", *pArr); printf("%d \n", *(++pArr)); printf("%d \n", *(++pArr)); printf("%d \n", *(pArr+1)); printf("%d \n", *(pArr+2)); return 0; } 그림 13-4
13-2포인터 연산 • 포인터와 배열을 통해서 얻을 수 있는 중대한결론 /* two_same.c */ #include <stdio.h> int main(void) { int arr[2]={1, 2}; int* pArr=arr; printf("%d, %d \n", arr[0], *(arr+1)); printf("%d, %d \n", pArr[0], *(pArr+1)); return 0; } 그림 13-5
13-3문자열 상수를 가리키는 포인터 • 문자열 표현 방식의 이해 • 배열 기반의 문자열 변수 • 포인터 기반의 문자열 상수 • str_prn.c 참조 char str1[5]="abcd"; char *str2="ABCD"; 그림 13-6
/* str_prn.c*/ #include <stdio.h> int main() { char str1[5]="abcd"; char *str2="ABCD"; printf("%s \n", str1); printf("%s \n", str2); str1[0]='x'; // str2[0]='x'; //Error ?! printf("%s \n", str1); printf("%s \n", str2); return 0; }
13-4 포인터 배열 • 포인터 배열 • 배열의 요소로 포인터를 지니는 배열 int* arr1[10]; double* arr2[20]; char* arr3[30]; 그림 13-8
13-4포인터 배열 • 포인터 배열 예제 1 /* ptr_arr.c */ #include <stdio.h> int main(void) { int a=10, b=20, c=30; int* arr[3]={&a, &b, &c}; printf("%d \n", *arr[0]); printf("%d \n", *arr[1]); printf("%d \n", *arr[2]); return 0; } 그림 13-9
13-4포인터 배열 • 포인터 배열 예제 2 /* str_arr.c */ #include <stdio.h> int main(void) { char* arr[3]={ "Fervent-lecture", "TCP/IP", "Socket Programming" }; printf("%s \n", arr[0]); printf("%s \n", arr[1]); printf("%s \n", arr[2]); return 0; } 그림 13-10 그림 13-11
14-1 함수의 인자로 배열 전달하기 • 기본적인 인자의 전달 방식 • 값의 복사에 의한 전달 그림 14-1
14-1 함수의 인자로 배열 전달하기 • 배열의 함수 인자 전달 방식 • 배열 이름(배열 주소, 포인터)에 의한 전달 #include <stdio.h> void fct(int *arr2); int main(void) { int arr1[2]={1, 2}; fct(arr1); printf("%d \n", arr1[0]); return 0; } void fct(int *arr2) { printf("%d \n", arr2[0]); arr2[0]=3; } 그림 14-2 그림 14-3
14-1 함수의 인자로 배열 전달하기 • 배열 이름, 포인터의 sizeof 연산 • 배열 이름 : 배열 전체 크기를 바이트 단위로 반환 • 포인터 : 포인터의 크기(4)를 바이트 단위로 반환 • arr_adder.c 참조 #include <stdio.h> int main(void) { int arr[5]; int* pArr=arr; printf(“%d \n”, sizeof(arr) ); // 20 출력 printf(“%d \n”, sizeof(pArr) ); // 4 출력 return 0; }
14-1 함수의 인자로 배열 전달하기 • "int * pArr" vs. "int pArr[ ]" • 둘 다 같은 의미를 지닌다. • 선언 "int pArr[ ]"은 함수의 매개 변수 선언 시에만 사용 가능 • max_fct.c 참조 int function(int pArr[]) { int a=10; pArr=&a; // pArr이 다른 값을 지니게 되는 순간 return *pArr; }
14-2 Call-By-Value와 Call-By-Reference • Call-By-Value • 값의 복사에 의한 함수의 호출 • 가장 일반적인 함수 호출 형태 #include <stdio.h> int add(int a, int b); int main(void) { int val1=10; int val2=20; printf(" 결 과 : ", add(val1, val2); return 0; } int add(int a, int b) { return a+b; }
14-2 Call-By-Value와 Call-By-Reference • Call-By-Value에 의한 swap int main(void) { int val1=10; int val2=20; swap(val1, val2); printf("val1 : %d \n", val1); printf("val2 : %d \n", val2); return 0; } void swap(int a, int b) { int temp=a; a=b; b=temp; printf("a : %d \n", a); printf("b : %d \n", b); } 그림 14-5
14-2 Call-By-Value와 Call-By-Reference • Call-By-Reference • 참조(참조를 가능케 하는 주소 값)를 인자로 전달하는 형태의 함수 호출 그림 14-6
14-2 Call-By-Value와 Call-By-Reference • Call-By-Reference에 의한 swap int main(void) { int val1=10; int val2=20; printf("Before val1 : %d \n", val1); printf("Before val2 : %d \n", val2); swap(&val1, &val2); //val1, val2 주소 전달 printf("After val1 : %d \n", val1); printf("After val2 : %d \n", val2); return 0; } void swap(int* a, int* b) { int temp=*a; *a=*b; *b=temp; } 그림 14-7
14-2 Call-By-Value와 Call-By-Reference • scanf 함수 호출 시 &를 붙이는 이유 • case 1 • case 2 int main(void) { int val; scanf("%d", &val); . . . . . int main(void) { char str[100]; printf("문자열 입력 : "); scanf("%s", str); . . . . .
14-3 포인터와 const 키워드 int a = 10; const int * p = &a; *p=30 // Error! a=30 // OK! • 포인터가 가리키는 변수의 상수화 • 포인터 상수화 그림 14-8 int a=10; int b=20; int * const p = &a; p=&b // Error! *p=30 // OK! 그림 14-9
14-3 포인터와 const 키워드 • const 키워드를 사용하는 이유 • 컴파일 시 잘못된 연산에 대한 에러 메시지 • 프로그램을 안정적으로 구성 #include <stdio.h> float PI=3.14; int main(void) { float rad; PI=3.07; // 분명히 실수!! scanf("%f", &rad); printf("원의 넓이는 %f \n", rad*rad*PI); return 0; } #include <stdio.h> const float PI=3.14; int main(void) { float rad; PI=3.07; // Compile Error 발생! scanf("%f", &rad); printf("원의 넓이는 %f \n", rad*rad*PI); return 0; }
Quiz 정답 Answer #1 temp = a; a = b; b = temp; Answer #2 n*Factorial(n-1) Answer #3 &num[i]; max < num[i] min > num[i]