360 likes | 522 Vues
포 인 터 (pointer). 난 예 찍었어 ( 삼송 ). 나는 예 찍었어 ( 에라이 다졌어팀 ). 포 인 터 (pointer). 포인터 포인터의 데이터형 * ptr++ 포인터 연산 void 형 포인터 포인터의 포인터 main 함수의 인수 근거리 (near)/ 원거리 (far) 포인터 함수 포인터 메모리 모델 동적 메모리 할당. 포 인 터 (pointer). 포인터 포인터도 하나의 데이터형 . 포인터는 임의의 대상체 (object) 를 가리킴 .
E N D
포 인 터(pointer) 난 예 찍었어(삼송) 나는 예 찍었어 (에라이 다졌어팀) Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
포 인 터 (pointer) • 포인터 • 포인터의 데이터형 • *ptr++ • 포인터 연산 • void형 포인터 • 포인터의 포인터 • main 함수의 인수 • 근거리(near)/원거리(far) 포인터 • 함수 포인터 • 메모리 모델 • 동적 메모리 할당 Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
포 인 터 (pointer) • 포인터 • 포인터도 하나의 데이터형. • 포인터는 임의의 대상체(object)를 가리킴. • 포인터는 대상체의 주소값(address)을 가짐. • 포인터가 가리킬 대상체의 데이터형을 반드시 명시. • 포인터의 크기 • 대상체의 데이터형과는 관계없이 항상 2bytes • 예외 : far pointer는 4bytes • 포인터의 선언 • 일반변수의 선언과 거의 같으나 선언해주는 포인터변수 앞에 * 를 붙임. * 를 꼭 사용해야함 int *pi; // 정수형 포인터 선언 char *pch; // 문자형 포인터 선언 Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
*pi가 가지는 번지값 *pi가 가지는 번지값 *pi가 읽어내는 값 *pi가 읽어내는 값 i ; ch ; 1234 ‘C’ 포인터의 데이터형 • 포인터의 데이터형은 포인터가 가리키게 될 대상체의 데이터형. • 포인터의 데이터형을 표현이유 • 대상체를 포인터를 이용해 읽어낼 경우 읽어야 할 byte 수와 비트 해석 방법을 명시화 하기 위해서 • 포인터가 연산을 통해 다른 대상체의 번지로 이동할 때의 이동 거리를 명시하기 위해서 #include <stdio.h> #include <conio.h> void main() { int i, *pi ; char ch, *pc; ch = ‘c’; pi =&i; //문자 및 정수형 포인터에 각각 값 대입. 정상적 printf(“integer is %d \n”, *pi ); // 정상적인 출력 pi = &ch; //정수형 포인터에 문자대입. 비정상적 printf(“integer is %d \n”, *pi ); // 비정상적인 출력 getch() } Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
포인터의 데이터형 • 포인터 변수의 간단한 연산 • 포인터 변수의 증감연산은 산술 연산과 차이가 있음. • 포인터 변수의 가감연산은 그 포인터 변수의 데이터형 만큼 가감. • 앞이나 뒤의 번지로 이동하고 싶다면 데이터 타입과는 상관없이 언제든지 px++ , px-- 연산자 사용. object 형의 포인터 변수 px 에 정수상수 i 를 더하면 px = px + (i 바이트)가 아니고 px = px + (i * sizeof(object) 바이트) 이다. #include <stdio.h> #include <conio.h> void main() { int ar[7] = { 1,2,3,4,5,6,7} ; int j, *ptr ; ptr = ar ; // ar의 번지를 ptr에 대입 printf(“ %d \n”, *ptr[2]+10 ); // 3+10 = 13 j = ++ *ptr ; // 2(1+1) printf(“ %d \n”, j ); getch() } Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
(a) *ptr++의 동작 1. 먼저 읽는다. 2. 값을 읽는다. 1. 먼저 읽는다. *ptr++ *++ptr 2. 포인터 변수를 증가시킨다. 2. 포인터 변수를 1 증가시킨다. 1. 포인터 변수를 1 증가시킨다. ptr (b) *++ptr의 동작 2. 값을 읽는다. 1. 포인터 변수를 증가시킨다. 최초 ptr ptr 이 값은 읽혀지지 않는다. *ptr++ • 연산 순위에 따른 *ptr++의 동작 Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
ptr ptr+i ……. ar[i+1] ar[i] ar[0] ar[1] ar[2] ar[3] i+1 번째 요소의 번지값 포인터 연산 • 포인터 연산의 제약 • 포인터의 가감연산은 포인터의 타입에 따라 가감 정도가 달라짐. • 포인터에 포인터를 더할 수는 없음.(번지값끼리 더한다는 것은 무의미) • 포인터에 정수를 더하는 것은 다음 위치로의 이동을 의미. • 포인터의 다음 위치를 선정. • 포인터에서 정수를 빼거나 더한 연산의 결과는 역시 포인터값. #include <stdio.h> #include <conio.h> void main() { int i=5, j=6; int *pi, *pj; printf(“%p”, pi+pj); // 포인터끼리 더함, 에러 발생 } Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
포인터 연산 • 포인터에서 포인터를 빼면 두 요소간의 상대적인 거리를 구할 수 있음. • 두 요소 사이의 메모리 크기는 그 값에 sizeof()을 곱해 주어야 함. #include <stdio.h> #include <conio.h> void main() { int ar[]={1, 2, 3, 4, 5, 6, 7}; int *first, *second; int memnum; first = &ar[0]; second = &ar[6]; memnum = (second - first) * sizeof(int); // 포인터끼리의 뺄셈 printf(“Memory size is %d bytes\n”, memnum); } 출력결과 : Memory size is 12 bytes Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
포인터 연산 • 포인터 연산의 상대적 거리 예제 -1 #include <stdio.h> #include <conio.h> void main() { int i=5, j=6 ; int *pi, *pj ; *pi = i ; *pj = j ; printf(“%p %p \n”, pi, pj ); // pi=0476 , pj=00D7 pi = i ; pj = j ; printf(“%p %p \n”, pi, pj ); // pi=0005 , pj=0006 } Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
포인터 연산 • 포인터연산의 상대적 거리 예제 -2 #include <stdio.h> #include <conio.h> void main() { int ar[]={1, 2, 3, 4, 5, 6, 7}; int *first, *second; first = &ar[0]; second = &ar[6]; printf(“%p %p \n”, first, second); // FFB8, FFC4 printf(“%p %p \n”, *first, *second); // 0001, 0007 } Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
ptr1=ptr2+(ptr3-ptr2)/2; 1. 포인터끼리의 뺄셈 = 정수 2. 정수 나누기 정수 = 정수 4. 대입가능 3. 포인터 더하기 정수 = 포인터값 포인터 연산 • 포인터끼리 뺄셈을 한 연산 결과의 데이터형은 더 이상 포인터값이 아닌 정수값. int *ptr1, *ptr2, *ptr3; ptr1=ptr2-ptr3; // 정수값을 포인터형에 대입할 수 없음. 대입가능한 식의 예 Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
포인터 연산 • 포인터에 곱셈이나 나눗셈도 불가능. • 포인터는 주소값이므로 이를 곱하거나 나누어 나오는 값은 무의미한 값이 되므로 C에서는 이러한 연산을 허용하지 않음. • 포인터는 서로 비교연산 가능.(==, !=, <. <=. >, >=) • 양쪽의 데이터 타입이 일치해야 함. • NULL값과는 비교가 가능. • 포인터끼리는 대입 가능. • 대입하는 두 포인터의 타입이 일치해야 함. • 만일 두 포인터의 타입이 일치하지 않으면 캐스트 연산자를 이용하여 강제로 타입을 맞추어 줌. int i, *pi; double d, *pd; pi=&i; pd=&d; pi=(int *)pd; // 캐스트 연산자를 사용하여 타입을 맞춘다. Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
포인터 연산 • 포인터 연산시의 주의 사항 • 포인터끼리의 연산은 항상 양쪽 포인터의 타입이 일치 해야 함. • 포인터끼리의 대입과 뺄셈, 비교는 가능하며 포인터끼리 뺄셈한 결과는 정수형이 됨 • 덧셈, 곱셈, 나눗셈은 불가능 • 포인터와 정수와의 덧셈, 뺄셈, 가감 연산은 가능하며 이 경우 가감의 정도는 포인터의 데이터 타입에 따라 좌우되고 연산결과는 여전히 포인터값을 지속. Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
void형 포인터 • void 형 • 대상체의 데이터형이 명시되어 있지 않은 포인터형 • 오직 메모리의 한 위치만을 나타낼 수 있도록 만들어진 변수 • void 형 포인터의 특징 • 포인터할 대상체가 정해져 있지 않음. • * 연산자를 void 형 포인터와 함께 사용해 메모리의 값을 읽어낼 수 없음. (void 형 포인터 변수에는 * 연산자 사용이 불가능하므로 *의 변형인 []연산자도 당연히 사용할 수 없음.) • 데이터형이 정해져 있지 않으므로 증감 연산자도 사용 불가. • NULL 포인터 • 0번지를 가리키고 있는 포인터(아무것도 가리키고 있지 않음 의미) • 일반적으로 NULL 포인터를 리턴하면 에러 발생. • void 형과 NULL의 비교 void 형 포인터 : 아무것이나 가리킬 수 있는 포인터 변수 NULL 포인터 : 아무것도 가리키고 있지 않다는 뜻의 포인터 상수 Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
&i &pi i=3 pi ppi 포인터의 포인터(이중포인터) • 포인터의 포인터 • 어떤 대상체의 번지를 가지고 있는 변수의 번지를 가지고 있는 변수. • 이중 포인터 포인터라고도 함. #include <stdio.h> void main() { int i, *pi, **ppi; i = 3; // ppi pi 의 주소값 pi = &i; // *ppi pi주소가 가지고 있는값. 즉 i의 주소값 ppi = π // **ppi i printf(“%d”, **ppi); // 3출력 printf(“%d %d %d ”, i, *pi, **ppi ); // 3 3 3 출력 } • i = *(pi) = *(*ppi) • &i = pi = *ppi • *&i = *&*pi = *&**ppi Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
포인터의 포인터 • 이중 포인터의 초기화 • 포인터의 포인터값을 대입 • 포인터 변수에 & 연산자를 붙여서 사용 • 포인터 변수의 대입 • 포인터변수도 메모리상에 번지값이 있으므로 그 번지값이 다른 포인터 변수에 대입될 수 있음. • & 연산자를 두 개 겹쳐서 쓰는 것은 위법 • & 연산자의 피연산자는 메모리상의 실제 번지를 점유하고 있는 좌변값이어야 하는데 &i는 포인터 상수일 뿐 좌변값이 아니기 때문 • &*i 도 불법, *&i는 사용가능 #include <stdio.h> void main() { int i, *pi, **ppi; i = 3; pi = &i; ppi = π // &&i=&pi=ppi 는 위법 printf(“%d”, **ppi); } Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
C:\> copy test.txt data.txt 인수들 main 함수의 인수 • main 함수의 인수 • 함수 호출시에 넘져지지 않고 DOS의 명령 행에서 프로그램을 실행시 전해짐. • main 함수의 원형 • return value • 프로그램 탈출 코드로 정수값 • argc • argument count • 인수의 개수. (위 예에서 인수의 개수는 3개) • argv • 인수의 실제값 (argument value) • argv는 포인터의 포인터형. 즉, 포인터의 포인터형(이중 포인터형). • argv[0]에는 copy, argv[1]에는 test.txt, argv[2]에는 data.txt가 저장 int main( int argc, char *argv[], char *env[] ); Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
main 함수의 인수 • env • environment • DOS의 환경 변수(path지정, prompt등등 DOS의 동작을 지시하는 변수)를 알려줌. • env인수는 리턴값과 함께 거의 사용되지 않음. #include <stdio.h> #include <conio.h> #include <stdlib.h> void main(int argc, char *argv[]) { int a, b; float c; char oper; if(argc!=4) { printf(“I need three parameter\n”); exit(0); } Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
a=atoi(argv[1]); //convert ascii to integer b=atoi(argv[3]); oper=argv[2][0]; switch(oper) { case ‘+’ : c=a+b; break; case ‘-’ : c=a-b; break; case ‘*’ : c=a*b; break; case ‘/’ : c=a/b; break; case ‘%’: c=a%b; break; default : printf(“I can’t understand this operator...”); exit(0); } printf(“The result is %g”, c); } 실행 c:\> test 300 + 20 결과 320 argv[3] argv[0] argv[1] argv[2] Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
4 bits 16 bits Segment + 16 bits Offset 20 bits Real Memory 원거리포인터(far pointer) • Far Pointer • 임의의 번지 지정을 위해 사용하는 세그먼트값과 오프셋값을 모두 가지고 있는 포인터변수(4bytes) • 1M 메모리 공간중 임의의 지점을 포인트하기 위해 세그먼트와 오프셋을 모두 가지고 있는 포인터 변수가 필요 • Near Pointer • 근거리포인터 • 일반적인 포인터로서 오프셋값만 가짐 (2bytes) • Segment & Offset Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
원거리포인터(far pointer) • 원거리 포인터의 선언 • 원거리 포인터를 조작할 수 있는 간단한 매크로 함수 • void far *MK_FP(unsigned seg, unsigned ofs); • 세그먼트와 오프셋값을 주면 far 포인터를 만듬 • FP_SEG • far 포인터로부터 세그먼트값만 읽음 • FP_OFF • far 포인터로부터 오프셋값만 읽음 char far *fpc; // 포인터의 선언과 거의 같으나 int far *fpi; // far이라는 키워드를 하나 더 넣는다 Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
함수 포인터 • 함수 포인터 • 함수를 가리키는 포인터 • 함수도 메모리상에 존재하므로 그 함수의 번지를 가리키는 포인터가 존재 • 함수 포인터는 그 함수가 위치한 메모리의 시작번지를 가리킴 • 함수 포인터의 선언 • type : 함수 포인터가 포인트할 함수의 리턴값 • 변수명: 함수 포인터의 이름 • 인수: 함수 포인터가 포인트할 함수가 취하는 인수 • 괄호: 생략 불가능, 괄호가 있는것과 없는것은 엄격히 차이가 있음 • type (*변수명)(인수) Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
함수 포인터 • 여러가지 선언들의 비교 1. 두개의 정수를 인수로 사용하고 리턴값이 없는 함수 2. 숫자와 연산자를 입력받아 정수형 포인터를 리턴하는 함수 3. 리턴값이 없는 함수에 대한 함수 포인터 4. char* 를 리턴하는 함수에 대한 함수 포인터 • 함수포인터를 선언하는 요령 1. void position(int x, int y); 2. int* compute(double* x, double* y, char ch); 3. void (*swap)(int *x, int *y); 4. char* (*listen)(void); void clear(void); void (*fpclear)(void); int calc(int, int*); int (*fpcalc)(int, int*); char* search(char *, char **) char* (*fpsearch)(char *, char **); Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
함수 포인터 #include <stdio.h> #include <conio.h> int mult2(int); /*함수의 원형 */ int mult3(int); /*함수의 원형 */ void main() { int num; char ch; int (*func)(int); /* 함수 포인터 선언 */ clrscr(); printf("input a number : "); scanf("%d",&num); printf("press 2 or 3 :\n"); ch=getch(); if (ch=='2') func=mult2; /* 입력값에 따라 함수 포인터 대입 */ else func=mult3; num=(*func)(num); /* 함수 호출 */ printf("%d",num); } int mult2(int num) { return num*2; } int mult3(int num) { return num*3; } Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
함수 포인터 • 수식내에서의 함수명 • 함수명이 수식내에서 단독으로 사용되면 함수의 시작 번지를 나타내는 포인터 상수 • 즉, 함수명 자체가 포인터 상수가 됨 • 함수 포인터 인수 • 인수로서의 함수 포인터 사용 • 함수 포인터를 인수로 취하는 함수의 공통적 특징 • 일반적으로 잘 사용되지 않음 • 잘 몰라도 C 프로그래밍을 하는데 큰 지장이 없음 int calc(int); int (*funptr)(int); funptr=calc; // 함수 포인터의 초기화 printf(“%d”, (*funptr)(3) ); // calc(3)과 동일한 역할을 한다 Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
함수 포인터 • atexit() • 프로그램이 실행을 종료하기 직전에 실행할 함수를 설정 #include <stdio.h> #include <conio.h> #include <stdlib.h> //atexit()함수 정의 void before_exit(void); void main() { atexit(before_exit); // 종료 처리 함수 지정, 성공적으로 함수의 // 수행이 종료되면 마지막으로 호출시킴 printf(“Now I am in main\n”); getch(); } void before_exit(void) // 종료 처리 함수 { printf(“Now I am about to exit\n”); getch(); } 결과 Now I am in main Now I am about to exit Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
메모리 모델 • 메모리 모델을 분류 기준 • 코드 세그먼트(Code Segment)와 데이터 세그먼트(Data Segment)의 사용정도 • 코드 세그먼트와 데이터 세그먼트 • 코 드 세그먼트: 함수가 들어있는 영역 • 데이터 세그먼트: 변수들이 저장되는 영역 • 메모리 모델의 비교(in Borland C++) Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
메모리 모델 • 메모리 모델 설정 • TC의 경우 Option->Compiler/Code Generation에서 변경 가능 • 모델 변경 후의 예제 • 포인터의 크기가 2인경우 • near pointer • 포인터의 크기가 4인경우 • far pointer(==huge pointer) #include <stdio.h> void main() { int *pi ; void (*pf)(void) ; //함수 포인터의 선언 printf(“sizeof(pi) = %d \n”, sizeof(pi)); printf(“sizeof(pf) = %d \n”, sizeof(pf)); } 결과 4 4 Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
CS DS, SS CS 64k를 넘을 수 없음 코드 세그먼트 코드 세그먼트 SS, DS 데이터 세그먼트 데이터 세그먼트 64k를 넘을 수 없음 heap heap 64k를 넘을 수 없음 stack stack tiny model small model 메모리 모델 • tiny model 과 small model의 비교 • 지역변수를 과다하게 사용할 경우 DS, CS영역을 Stack Segment가 침범하므로 프로그램의 오류가 발생 • 따라서, 메모리 모델은 일반적으로 large model이나 huge model을 이용함. • CS: Code Segment • DS: Data Segment • SS : Stack Segment Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
메모리 모델 • com 파일과 exe 파일의 비교 • com 파일 • 데이터세그먼트(DS)와 코드세그먼트(CS)가 한 세그먼트(64k) 안에 들어있는 파일. • 같은 영역 내에 데이터와 코드(본체부분)이 모두 있으므로 실행 속도가 빠름. • 데이터와 코드가 동일 영역 안에 있어야 하므로 덩치가 작은 프로그램에 적합. • exe 파일 • 데이터 세그먼트와 코드 세그먼트가 다른 영역에 들어 있는 파일. • 모델에 따라서는 데이터도 아주 많고 코드의 덩치도 큰 대형 프로그램을 제작하기에 매우 용이. • 데이터 세그먼트와 코드 세그먼트가 다른 영역에 있어 속도가 다소 저하됨. • 그러나 요즘은 같은 크기의 프로그램을 작성했을 때 속도의 차이를 거의 느낄 수 없음. • 위에서 비교한 모델(6가지)을 참조하여 자신이 작성할 프로그램에 가장 적당한 모델을 찾아서 프로그래밍해야 함. Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
동적 메모리 할당 • 메모리의 할당 • 정적 할당 • 프로그램이 실행될 때 할당되는 메모리. • 이 메모리는 프로그램이 종료되기 전까지 그대로 존재. • 동적 할당 • 프로그램 실행 중에 요청에 의해 할당되는 메모리. • 필요하면 메모리가 존재하는 한 언제든지 할당 받을 수 있고 다 쓴 후에는 반납을 하여 다른 곳에서 필요하면 쓸 수 있도록 해 주는 메모리 할당 기법. Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
프로그램자체 정적 데이터 영역 near heap stack far heap 동적 메모리 할당 • 메모리 할당 규칙(DOS) • 할당 요청이 있으면 메모리가 있는 한 메모리를 할당. • 할당 요청이 있으면 빈 메모리 공간의 최저 위치를 할당. • 한번 할당된 메모리는 다른 할당 요청에 대해 다시 할당 않음. • 할당된 메모리가 반납되면 다른 할당 요청에 의해 메모리가 다시 할당 가능. • 더 이상 할당할 메모리가 없으면 할당이 취소되고 에러값을 반환. (프로그램에서는 이 경우 반드시 에러 처리 루틴 필요) Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
동적 메모리 할당 • 메모리 할당 함수들 void *malloc(size_t size); void free(void *block); void far *farmalloc(unsigned long nbytes); void farfree(void far *block); void *calloc(size_t ntimes, size_t size); void *realloc(void *block, size_t size); void far *farrealloc(void far *oldblock, unsigned long nbyes); Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
동적 메모리 할당 • 예제 • malloc(), free()를 이용한 동적메모리 할당 예제 #include <stdio.h> #include <alloc.h> /* 메모리 할당함수 정의 */ #include <conio.h> /* clrscr()정의 */ #include <stdlib.h> /* 메모리 할당함수 정의 */ void main() { int *pi; int i; clrscr(); pi = (int *)malloc(10*sizeof(int)); /* memory 할당 */ if (pi == NULL) exit(0); for (i=0;i<10;i++) /* 할당된 memory에 값을 저장 */ pi[i]=i; for (i=0;i<10;i++ ) /* 저장한 값을 다시 읽음 */ printf("%d ",pi[i] ); free(pi); /* memory 반납 */ } 결과 : 0 1 2 3 4 5 6 7 8 9 Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
동적 메모리 할당 • 예제 • farmalloc(), farfree()를 이용한 동적메모리 할당 예제 • 이는 원거리 heap을 할당하고 해제하는 함수로서 일반 malloc()함수와 동일하지만 far heap을 할당받는 것만 다름. #include <stdio.h> #include <alloc.h> /*동적메모리 함수 정의 */ #include <stdlib.h> /* 동적메모리 함수 정의 */ void main() { int i, far *pi; pi = (int far *)farmalloc(10*sizeof(int)); /*far heap 할당 함수 */ if (pi == NULL) exit(0); for ( i=0 ; i<20 ; i++ ) pi[i] = i; for ( i = 0 ; i<20 ; i++ ) printf(” %d ",pi[i] ); farfree(pi); /*far heap 할당 해제 함수*/ } 결과 : 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ……..19 Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr
Report • 즐거운 Report • 임의의 수를 3개 입력 받아서 이 숫자들을 큰 순서대로 나열하고 그 합과 평균을 구하는 프로그램을 작성하세요… ^^ • 프로그램 실행 후 숫자들을 차례로 입력 받게 작성하세요. • 프로그램을 실행시킬 때 메인 함수의 인수로 숫자들을 넣을 수 있도록 하세요. • heap과 stack에 대해서 조사해 오세요..(메모리 할당측면에서) • 메모리 할당/해제 함수에 대하여 조사해 오세요…(예제와 함께) Yang, Ok Yul / cache@wonnms.wonkwang.ac.kr