210 likes | 359 Views
학습 내용. 포인터 개념 포인터 연산자 배열 및 포인터 포인터에 의한 인수 전달 Call by value 및 Call by reference main 함수에서의 인수 전달. 메모리. 번지. 0 1 …. …. q. XXX( 값 ). 100. p. 100( 번지 ). 포인터 개념. 포인터는 다른 개체 ( 변수 ) 의 메모리 주소를 저장하는 변수이다 .
E N D
학습 내용 • 포인터 개념 • 포인터 연산자 • 배열 및 포인터 • 포인터에 의한 인수 전달 • Call by value 및 Call by reference • main 함수에서의 인수 전달
메모리 번지 0 1 … ….. q XXX(값) 100 p 100(번지) 포인터 개념 • 포인터는 다른 개체(변수)의 메모리 주소를 저장하는 변수이다. • 포인터 변수 p가 q라는 다른 변수의 주소를 저장하고 있다면, p는 q를 가르킨다라고 한다. 즉 q가 메모리 100번지에 있다면 p의 실제 값은 100이 된다.
포인터 선언 및 연산자 • 포인터의 선언 • 형식 : [데이터 형] * 변수이름 • [데이터 형] : 포인터가 가르키는 개체(변수)의 데이터 형 • 예) int *p; -> 정수형 데이터의 주소를 가질수 있는 포인터 변수 p를 선언 • 포인터 연산자 • * : 뒤에 오는 피연산자(주로 포인터)의 주소에 들어 있는 값을 반환 • & : 뒤에 오는 피연산자(주로 변수)의 주소를 반환 • 예) *p : p라는 포인터 변수의 주소에 들어있는 값 &q : q라는 변수가 들어있는 메모리 주소
예제 #include <stdio.h> int main(void) { int *p, q; p = &q; *p = 200; printf(“%d”, q); return 0; } #include <stdio.h> int main(void) { int *p, q; q = 100; p = &q; printf(“%d”, *p); return 0; }
포인터 연산식 • 포인터에 수행할 수 있는 연산자: *, &, +, ++, -, -- • +, - 등의 산술 연산자는 정수와만 가능 • i = *(p+2); -> 가능 • i = *(p+2.5); -> 불가능 • 포인터의 증가, 감소는 포인터가 가르키는 데이터 형과 밀접한 관계가 있다. • p가 short형 포인터이고 현재 200번지를 가르킨다면, p++ 수행 이후의 p 값은 202가 된다. • 만약 p가 float 또는 int(32비트 환경)형 포인터면 204가 된다. • p가 char형이면 당연히 201이 된다. • *p++ : 포인터를 하나 증가시킨 다음, 그 번지에 들어 있는 값, 즉 연산자 우선순위 상 *(p++)와 동일 • (*p)++ : 포인터 번지에 들어있는 값을 하나 증가시킨다.
배열과 포인터 • 포인터와 배열은 매우 밀접한 관계를 가지며, 종종 서로 혼용해서 사용 가능하다. • 배열의 이름은 배열의 시작 부분에 대한 포인터 상수가 된다.즉 배열이름은 배열이 저장되는 시작 주소가 된다. • 예 #include <stdio.h> int main(void) { int a[5] = {1,2,3,4,5}; /* 결국 a = &(a[0]) */ int *p; p = a; printf(“\n%d %d %d”, *p, *(p+1), *(p+2)); printf(“\n%d %d %d”, a[0], a[1], a[2]); return 0; }
메모리 번지 0 1 … ….. ch 100 ‘A’ ….. p 100 200 ….. mp 200 다중 포인터 • 포인터가 다른 포인터를 가르키는 것이 가능하다. • 예) char **mp, *p, ch; p = &ch; mp = &p; **mp = ‘A’;
문자열 배열 • 문자열 배열 • 가장 많이 사용되는 포인터 배열 • 문자열들을 효율적으로 저장할 수 있다. char *fruits[ ] = { "apple", "blueberry", "orange", “melon" };
포인터의 활용 • 지금까지의 간단한 예제 등에서 포인터는 별 필요성이 없어 보인다. • 하지만 좀 더 C를 공부하고 큰 규모의 프로그램을 작성할 경우에 포인터는 꼭 필요한 부분이다. • 특히 연결리스트, 트리 등의 복잡한 자료구조의 활용이나 함수들의 매개 변수에서 포인터는 필수적인 존재이다.
예제 1)정수 배열에 있는 데이터의 총합을 구하는 예제를 완성하시오. #include <stdio.h> int array_sum(int* , int); int main(void) { int a[5], i, sum; for(i=0; i<5; i++) scanf("%d",&a[i]); sum = array_sum(a, 5); printf("Array Sum : %d", sum); return 0; } int array_sum(int *array, int count) { }
실습 예제 2)입력한 문자열의 문자 개수를 구하는 프로그램을 앞의 예제와 흡사하게 사용자 정의 함수로 만드시오. • 실습 예제 1)정수 배열에 들어 있는 값 중에서 최고 값을 구하는 프로그램의 앞의 예제와 흡사하게 사용자 정의 함수 형식으로 작성하시오. • 실습 예제 3)문자열을 인수로 받아 이 문자열의 소문자를 모두 대문자로 변경하는 프로그램을 사용자 정의 함수를 이용하여 작성하시오.
Call by value(값에 의한 전달) • C언어에서 매개 변수 전달은 값을 복사하여 전달한다. • 다음 코드를 분석해보자. #include <stdio.h> void swap(int i, int j); int main(void) { int a=3, b=5; printf("\n a = %d b = %d",a,b); swap(a,b); printf("\n a = %d b = %d",a,b); return 0; } void swap(int i, int j) { int temp; temp=i; i=j; j=temp; return; }
Call by Reference(참조에 의한 전달) • Call by address 라고도 불린다. • 몇몇 언어에서는 함수로 매개 변수를 전달할 때, 인수의 주소를 직접 전달하기도 한다. • C언어에서 앞에서 본 바와 같이 기본적으로 매개 변수 전달 시에 값에 의한 전달을 사용함으로 참조에 의한 전달은 인의적으로 포인터를 이용하여 사용할 수 있다. • 다음은 앞의 Swap 함수를 포인터로 이용하여 강제로 참조에 의한 전달로 변환한 예이다.
#include <stdio.h> void swap(int *i, int *j); int main(void) { int a=3, b=5; printf("\n a = %d b = %d",a,b); swap(&a,&b); printf("\n a = %d b = %d",a,b); return 0; } void swap(int *i, int *j) { int temp; temp=*i; *i=*j; *j=temp; return; } 참고 : scanf 함수에서 입력받는 변수 앞에 & 연산자를 붙이는 이유는 무엇일까?
여러 개의 리턴 값을 가지는 함수 • 원칙적으로 C언어에서는 여러 개의 리턴 값을 가지는 함수는 존재하지 않는다. 즉 C 언어에서는 하나의 값만 리턴할 수 있다. • 앞의 참조에 의한 전달 방법을 사용하여 여러 개의 리턴 값을 가지는 효과를 갖는 함수를 구성할 수 있다. • 다음의 예제는 두개의 값을 전달 받아, 합계와 평균을 계산하는 함수의 예이다.
#include <stdio.h> void cal(int i, int j, int *sum, float *ave); int main(void) { int a, b, sum; float ave; scanf("%d%d",&a,&b); cal(a,b, &sum, &ave); printf("\n a = %d b = %d sum = %d average = %4.1f“ ,a,b,sum,ave); return 0; } void cal(int i, int j, int *sum, float *ave) { *sum = i+j; *ave = (i+j)/2.0; return; }
실습 예제4)정수형 배열과 배열 개수를 인수로 받아서 배열의 총합과 평균 값을 전달해 주는 사용자 정의 함수를 작성하시오. void sum_ave(int array[], int count, int *sum, double *ave); • 실습 예제5)정수형 배열 A[]와 B[]의 차를 구하여 배열 C[]에 저장하는 함수(배열 A-B)를 작성하고 테스트 하시오. 배열의 원소 개수는 count 변수로 전달된다. void array_sub(int *A, int *B, int count, int *C);
main 함수의 인수 • 명령어 라인 인수란 운영체제에 명령어 라인에서 실행 프로그램 이름 뒤에 사용하는 정보를 말한다. • 예를 들어 윈도우의 “명령프롬프트” 창에서 “hwp test.hwp”라고 입력하면 hwp라는 프로그램은 명령어 인수에서 test,hwp를 전달 받아야 한다. • C언어에서 명령어 라인 인수는 main 함수의 두개의 인수(argc, argv)로 넘겨진다. • 두 인수의 데이터 형 • int argc : 인수의 개수(프로그램 이름 포함) • char *argv[] : 인수의 내용이 문자열 포인터 배열로 argv[0] : 프로그램 이름 argv[1] : 첫번째 인수 내용, …
main 인수 예제 #include <stdio.h> int main(int argc, char *argv[]) { int i; printf("\n Count of arguments : %d", argc); printf("\n Contents of arguments : "); for(i=0; i<argc;i++) printf("%s ",argv[i]); return 0; }
main 인수 실습 예제 • 실습 예제6) 명령어 인수로 두 수를 넘겨 받아 두수의 합과 평균을 출력하는 프로그램을 작성하시오. C:\Visual ~\debug> test 10 20 sum : 30 ave : 15.0 • 주의 1: Visual Studio에서 작성한 소스코드를 실행 파일로 만든 다음, 그 실행 파일의 폴더 위치의 “명령프롬프트 창”에서 실행해야 함 • 주의 2: 인수는 무조건 문자열로 넘어옴으로 이를 숫자로 변환해서 계산해야 한다. 다음의 함수를 이용하시오.(이들 함수를 사용하기 위해서는 stdio.h 이외 stdlib.h를 include해야 한다. • int atoi(char *str); • double atof(char *str); • char *itoa(int *a); …
참고: 유용한 C 라이브러리 함수 • 문자열 처리 관련 함수(string.h) • strlen, strcpy, strcat, strncpy, strcmp, strncmp, strstr, strchr, strtok, … • 문자 처리 관련 함수(ctype.h) • isalpha, isupper, islower, isdigit, isalnum, … • toupper, tolower • 문자열 수치변환(stdlib.h) • atoi, atol, atof, itoa, itol, … • 문자열에서 변수 입력, 또는 변수 값을 문자열로 출력 • sscanf, sprintf