2.4k likes | 2.59k Views
C++ & OOP. 강사 : 이준근 (egenie@korea.com). 제 1 장. Windows System. 가상 메모리. 모든 어플리케이션은 컴퓨터에 설치된 RAM 의 양에 관계없이 4GB 의 메모리 어드레스 공간을 가지는 컴퓨터에서 실행중인 것처럼 동작한다. FFFF FFFF. 2GB 운영체제를 위해 예약된 공간. 8000 0000. 2GB 애플리케이션 을 위한 공간. 7FFF FFFF. 0000 0000. 가상 메모리. 가상 메모리. 물리적메모리. 가상 메모리.
E N D
C++ & OOP 강사 : 이준근 (egenie@korea.com)
제1장 Windows System
가상 메모리 • 모든 어플리케이션은 컴퓨터에 설치된 RAM의 양에 관계없이 4GB의 메모리 어드레스 공간을 가지는 컴퓨터에서 실행중인 것처럼 동작한다. FFFF FFFF 2GB 운영체제를 위해 예약된 공간 8000 0000 2GB 애플리케이션 을 위한 공간 7FFF FFFF 0000 0000
가상 메모리 가상 메모리 물리적메모리
가상 메모리 • 가상 메모리는 메모리의 단지 논리적인 모습일 뿐이다. • 물리적인 메모리가 가상 메모리 보다 적기 때문에, 메모리 관리자는 사용이 가장 오래된 내용은 디스크에 옮긴다. • 디스크에 페이징된 가상 메모리를 액세스할 때는 가상 메모리 관리자는 디스크에 있는 정보를 메모리로 다시 옮긴다.
커널 모드 vs. 사용자 모드 • 사용자의 응용프로그램이 운영체제의 중요한 데이터를 액세스하고 수정하는 것을 방지하기 위해서, 사용자 모드와 커널 모드를 사용한다. • 사용자 모드 • 사용자 응용프로그램은 사용자 모드에서 실행된다. • 커널 모드 • 운영 체제 코드는 커널 모드에서 실행된다. • 사용자의 잘못된 프로그램이 시스템을 해쳐서 시스템이 다운되는 것을 막는다. • 사용자 모드는 개인 메모리 영역에서 실행된다. • 커널 모드는 하나의 주소 공간에서 실행되며 여러 사용자 프로그램이 공유한다.
주소 공간 배치 • 0x0000 0000부터 0x0000FFFF (64K) • NULL Pointer영역 • 액세스 불가 영역 • 이 영역내의 주소에 액세스하기 위한 시도는 액세스 위반을 일으킨다. #include <stdio.h> void main() { int * p = NULL; *p = 10; }
주소 공간 배치 • 0040 0000 : • 사용자 프로그램 코드가 올라가는 위치 • main() 함수가 올라가는 위치 #include <stdio.h> void main() { void ( * p)(); p = main; printf("Main함수의 주소 => %p\n",p); }
주소 공간 배치 • 0001 0000부터 7FFE FFFF • 사용자 주소 공간 • 스텍,힙,코드공간,전역공간이 이 영역에 배치된다. • 7FFD E000부터 7FFF FFFF • 첫번째 스레드 환경블록 • 프로세스 환경블록 • 사용자 공유 영역 • 액세스 불가 영역 등… • 8000 0000부터 FFFF FFFF • 시스템 영역 • 커널모드로만 접근 가능 • 사용자 프로그램 접근 불가.
주소 공간 배치 #include <stdio.h> void main() { int * p; printf("p의 값 => %p\n",p); *p = 0; }
제2장 C 기초 정리
메모리의 4가지 영역 • 스택 • 지역변수, 함수의 매개 변수가 저장된다. • 읽기,쓰기 가능 • 변수의 이름으로 접근한다. • 내용이 지속되지 않는다. • 함수가 시작되면 변수는 만들어 지고, 함수가 종료되면 변수는 자동적으로 지워진다. • 최대 1M까지 사용할 수 있다. #include <stdio.h> void main() { char p[1024][1024]; }
메모리의 4가지 영역 #include <stdio.h> void main() { char p; printf("%p\n",&p); }
메모리의 4가지 영역 • 코드영역 • 프로그램 코드가 저장된다. • 읽기 가능,쓰기 불가 #include <stdio.h> void main() { char * p; p = (char *)main; printf("%c",*p); }
메모리의 4가지 영역 #include <stdio.h> void main() { char * p; p = (char *)main; *p = 'a'; }
메모리의 4가지 영역 • 전역 공간 • 전역변수가 저장되는 공간 • 스택처럼 이름을 붙일 수 있다. • 이름으로 접근. • 전역 공간은 2부분으로 나뉜다. • 1. 전역 변수가 저장되는 공간. • 읽기,쓰기 가능 • 2. 상수가 저장되는 문자열 테이블 • 읽기 가능,쓰기 불가능 #include <stdio.h> void main() { char * p = "비트캠프"; *p = 'a'; }
메모리의 4가지 영역 • 자유 기억 공간 • 다량의 메모리 집합이다. • 변수를 만들 수 없다. • 포인터변수로 접근해야 한다. • 함수가 종료돼도 값을 계속 유지한다. • 메모리를 지우려면 free해줘야 한다. • 프로그램이 종료되면 모두 지워진다.
스택과 함수 • 함수로 분기될 때 일어나는 과정 • 1. 함수 호출 다음 주소를 스택에 저장한다. • 함수 호출이 끝난 뒤 되돌아갈 주소 • 2. 함수에서 선언한 반환형이 저장될 만큼의 공간이 만들어 진다. • 공간만 만들어지고 형(int,float..)으로는 만들어 지지 않는다. • 3. 호출된 함수의 주소가 명령포인터에 저장된다. • 4. 스택의 현재의 꼭대기가 특별히 표시된다. • 스택 프레임 • 4. 함수의 인자들이 스택에 위치한다. • 5. 명령어 포인터에 있는 명령어가 수행됩니다. • 6. 지역 변수들이 스택에 쌓인다. • 7. return문을 만나면 2번 과정에서 할당된 공간을 지정한 형으로 만들고 값을 copy합니다. • 8. 스택 프레임 포인터에 잡혀있는 스택까지를 모두 꺼낸다. • 9. 반환 값이 꺼내어져 함수 호출 그 자체의 값에 할당된다. • 10. 1번 과정에서 저장된 스택의 값이 명령포인터에 저장된다.
배열 #include <stdio.h> void main() { int a[5],b[5],c[5]; int i; for(i = 0;i < 5;i++) { a[i] = i; } for(i = 0;i < 5;i++) { b[i] = i; } for(i = 0;i < 5;i++) { c[i] = i; } for(i = 0;i < 5;i++) { printf("a[%d] = %d\n",i,a[i]); } for(i = 0;i < 5;i++) { printf("b[%d] = %d\n",i,b[i]); } for(i = 0;i < 5;i++) { printf("c[%d] = %d\n",i,c[i]); } }
배열 • 울타리 말뚝 오류 • 배열의 끝을 넘어 값을 다루는 오류 • 컴파일러에서 에러를 출력하지 않는다. • 실행 시에 에러가 난다.
배열 #include <stdio.h> void main() { int a[5],b[5],c[5]; int i; for(i = 0;i < 5;i++) { a[i] = i; } for(i = 0;i <= 5;i++) { b[i] = i; } for(i = 0;i < 5;i++) { c[i] = i; } for(i = 0;i < 5;i++) { printf("a[%d] = %d\n",i,a[i]); } for(i = 0;i < 5;i++) { printf("b[%d] = %d\n",i,b[i]); } for(i = 0;i < 5;i++) { printf("c[%d] = %d\n",i,c[i]); } }
배열 • 스택은 위에서부터 아래로 잡힌다.
배열 #include <stdio.h> void main() { int a[5],b[5],c[5]; int i; for(i = 0;i < 5;i++) { a[i] = i; } for(i = 0;i <= 9;i++) { b[i] = i; } for(i = 0;i < 5;i++) { c[i] = i; } for(i = 0;i < 5;i++) { printf("a[%d] = %d\n",i,a[i]); } for(i = 0;i < 5;i++) { printf("b[%d] = %d\n",i,b[i]); } for(i = 0;i < 5;i++) { printf("c[%d] = %d\n",i,c[i]); } }
배열 #include <stdio.h> void main() { int a[5],b[5],c[5]; int i; for(i = 0;i < 5;i++) { a[i] = i; } for(i = 0;i <= 10;i++) { b[i] = i; } for(i = 0;i < 5;i++) { c[i] = i; } for(i = 0;i < 5;i++) { printf("a[%d] = %d\n",i,a[i]); } for(i = 0;i < 5;i++) { printf("b[%d] = %d\n",i,b[i]); } for(i = 0;i < 5;i++) { printf("c[%d] = %d\n",i,c[i]); } }
배열 #include <stdio.h> #include <string.h> void main() { char name[10]; strcpy(name,"홍길동"); printf("%s\n",name); } #include <stdio.h> #include <string.h> void main() { char name[10]; strcpy(name,"123456789012"); printf("%s\n",name); }
배열 #include <stdio.h> #include <string.h> void main() { char name[10]; strcpy(name,"1234567890123"); printf("%s\n",name); }
배열 #include <stdio.h> #include <string.h> void main() { int i; char name[10]; strcpy(name,"1234567890123"); printf("%s\n",name); }
배열 #include <stdio.h> #include <string.h> void main() { char name[10]; printf("name => %p\n",name); printf("&name => %p\n",&name); }
배열 #include <stdio.h> void func(int b[]); void main() { int i; int a[5]; for(i = 0;i < 5;i++) { a[i] = i; } for(i = 0;i < 5;i++) { printf("a[%d] = %d\n",i,a[i]); } func(a); for(i = 0;i < 5;i++) { printf("a[%d] = %d\n",i,a[i]); } } void func(int b[]) { int i; for(i = 0;i < 5;i++) { b[i] = i*i; } } • 배열을 함수의 파라미터로 넘기기
포인터 연산자 내 용 & 1. 번지 연산자 2. 변수의 주소 번지를 표시 • 포인터를 사용하는 이유 • Call by reference • 자유 저장 영역을 관리하기 위해서 * 1. 간접 연산자 2. 포인터의 선언 3. 포인터가 지시하는 곳의 내용
포인터 #include <stdio.h> main() { int * ptr,num,val; ptr = # num = 100; printf("1. %d\n", *ptr); val = 200; ptr = &val; printf("2. %d\n", *ptr); ptr = # *ptr = 300; printf("3. %d\n", num); }
포인터 #include <stdio.h> main() { char c1,c2,c3,c4, * a; c1 = 'a'; c2 = 'c'; c3 = 'd'; c4 = ' '; a = "ABC EFG"; printf("%c%c%c%c",c1,c2,c3,c4); printf("%s\n",a); } • a = “ABC EFG”; • 포인터 변수 a에 문자열 상수를 치환하면 • a 에 문자열 상수가 있는 곳의 주소가 치환된다. • c1 = ‘a’; • char변수 c1에 ‘a’를 치환하면 • c1변수에 ‘a’의 ASCII코드 값이 들어간다.
포인터 #include <stdio.h> void swap(int x,int y); main() { int a,b; a = 3; b = 10; printf("a = %d, b = %d\n",a,b); swap(a,b); printf("a = %d, b = %d\n",a,b); } void swap(int x,int y) { int temp; temp = x; x = y; y = temp; } • Call by reference
포인터 #include <stdio.h> void swap(int * x,int * y); main() { int a,b; a = 3; b = 10; printf("a = %d, b = %d\n",a,b); swap(&a,&b); printf("a = %d, b = %d\n",a,b); } void swap(int * x,int * y) { int temp; temp = *x; *x = *y; *y = temp; } • 파라미터로 보낸 변수의 값을 바꾸려면 변수의 주소를 보내라.
포인터 #include <stdio.h> void swap(int * x,int * y); main() { int a,b; int * pa, * pb; a = 3; b = 10; pa = &a; pb = &b; printf("pa = %p, pb = %p\n",pa,pb); printf("a = %d, b = %d\n",a,b); swap(pa,pb); printf("pa = %p, pb = %p\n",pa,pb); printf("a = %d, b = %d\n",a,b); } void swap(int * x,int * y) { int temp; temp = *x; *x = *y; *y = temp; } • 파라미터가 포인터 변수 일 때 • 포인터 변수가 참조하는 변수의 값을 바꾸려면 그대로 포인터 변수를 보내라. • 파라미터 변수의 값을 바꿀 때만 파라미터 변수의 주소를 보낸다.
포인터 #include <stdio.h> void swap(int ** x,int ** y); main() { int a,b; int * pa, * pb; a = 3; b = 10; pa = &a; pb = &b; printf("pa = %p, pb = %p\n",pa,pb); printf("a = %d, b = %d\n",a,b); swap(&pa,&pb); printf("pa = %p, pb = %p\n",pa,pb); printf("a = %d, b = %d\n",a,b); } void swap(int ** x,int ** y) { int * temp; temp = *x; *x = *y; *y = temp; } • 더블포인터를 사용하는 경우 • 파라미터로 보내는 포인터 변수의 값을 바꿀때 • 내부 알고리즘은 변화가 없다. • 포인터도 일반 변수다. • 더블 포인터도 일반 변수다.
포인터와 내부 배열 char s[80]; char * p; p = s; char s[80]; char * p; p = &s[4]; • int * p; • const int * p; • p가 포인팅하는 곳의 값이 const • *p = 10 // error • p++; • int * const p; • p변수가 const • 의미 적으로 배열과 동일하다. • *p = 10; • p++; // error • const int * const p; • p변수와 변수가 포인팅하는 곳의 값도 const
포인터와 내부 배열 #include <stdio.h> main() { int num[5] = {15,36,270,69,57}; int i; for ( i = 0;i < 5;i++) { printf("%d ",num[i]); } printf("\n"); for ( i = 0;i < 5;i++) { printf("%d ",*(num + i)); } printf("\n"); }
포인터와 내부 배열 #include <stdio.h> void sum1(int dt [], int n); void sum2(int * dt,int n); main() { int a[5] = {1,2,3,4,5}; sum1(a,5); sum2(a,5); } void sum1(int dt[],int n) { int s = 0,i; for (i = 0;i < n;i++) { s += dt[i]; } for (i = 0;i<5;i++) { dt[i] = i; } printf("sum = %d\n",s); } void sum2(int * dt,int n) { int s = 0,i; for (i = 0;i < n;i++,dt++) { s += *dt; } printf("sum = %d\n",s); }
함수 포인터 • int fptr(); int를 return하는 함수 • int * fptr(); int *를 return하는 함수 • int (*fptr)() ; int를 반환하는 함수의 포인터 • 반환자료형 (*포인터 명)();
함수 포인터 #include <stdio.h> void sum(int a,int b); void sub(int a, int b); main() { void (* fun)(int a,int b); int a = 10, b = 3; fun = sum; fun(a,b); fun = sub; fun(a,b); } void sum(int a,int b) { printf("sum : %d\n",a + b); } void sub(int a,int b) { printf("sub : %d\n",a - b); }
구조체 • 구조체의 선언 • struct 태그명 { 멤버 리스트 }; • struct 태그명 변수 리스트; • struct man • { • char name[20]; • char sex; • int age; • };
구조체 #include <stdio.h> struct man { char name[20]; char sex; int age; }; main() { struct man teacher, *ptr; ptr = &teacher; strcpy(teacher.name,"Kim"); teacher.sex = 'm'; teacher.age = 30; printf("Name: %s\n",teacher.name); printf("Sex: %c\n",teacher.sex); printf("Age: %d\n",teacher.age); ptr->age = 40; printf("Name: %s\n",ptr->name); printf("Sex: %c\n",ptr->sex); printf("Age: %d\n",ptr->age); }
구조체 #include <stdio.h> #include <string.h> #include <stdlib.h> struct man { char * name; char sex; int age; }; main() { struct man teacher, teacher2; teacher.name = (char *)malloc(4); strcpy(teacher.name,"Kim"); teacher.sex = 'm'; teacher.age = 30; printf("Name: %s\n",teacher.name); printf("Sex: %c\n",teacher.sex); printf("Age: %d\n",teacher.age); teacher2 = teacher; printf("Name: %s\n",teacher2.name); printf("Sex: %c\n",teacher2.sex); printf("Age: %d\n",teacher2.age); strcpy(teacher2.name,"Lee"); printf("Name: %s\n",teacher.name); printf("Sex: %c\n",teacher.sex); printf("Age: %d\n",teacher.age); printf("Name: %s\n",teacher2.name); printf("Sex: %c\n",teacher2.sex); printf("Age: %d\n",teacher2.age); }
구조체 #include <stdio.h> #include <string.h> #include <stdlib.h> struct man { char * name; char sex; int age; }; main() { char temp[256]; struct man teacher, teacher2; printf("teacher 이름 : "); gets(temp); teacher.name = (char *)malloc(strlen(temp)+1); strcpy(teacher.name,temp); teacher.sex = 'm'; teacher.age = 30; printf("Name: %s\n",teacher.name); printf("Sex: %c\n",teacher.sex); printf("Age: %d\n",teacher.age); printf("teacher 이름 : "); gets(temp); teacher2.name = (char *)malloc(strlen(temp)+1); strcpy(teacher2.name,temp); teacher2.sex = 'm'; teacher2.age = 30; printf("Name: %s\n",teacher2.name); printf("Sex: %c\n",teacher2.sex); printf("Age: %d\n",teacher2.age); teacher2 = teacher; strcpy(teacher2.name,"Lee"); printf("Name: %s\n",teacher.name); printf("Sex: %c\n",teacher.sex); printf("Age: %d\n",teacher.age); printf("Name: %s\n",teacher2.name); printf("Sex: %c\n",teacher2.sex); printf("Age: %d\n",teacher2.age); free(teacher.name); free(teacher2.name); }
구조체 #include <stdio.h> #include <string.h> #include <stdlib.h> struct man { char * name; char sex; int age; }; main() { char temp[256]; struct man teacher, teacher2; printf("teacher 이름 : "); gets(temp); teacher.name = (char *)malloc(strlen(temp)+1); strcpy(teacher.name,temp); teacher.sex = 'm'; teacher.age = 30; printf("Name: %s\n",teacher.name); printf("Sex: %c\n",teacher.sex); printf("Age: %d\n",teacher.age); printf("teacher 이름 : "); gets(temp); teacher2.name = (char *)malloc(strlen(temp)+1); strcpy(teacher2.name,temp); teacher2.sex = 'm'; teacher2.age = 30; printf("Name: %s\n",teacher2.name); printf("Sex: %c\n",teacher2.sex); printf("Age: %d\n",teacher2.age); //teacher2 = teacher; free(teacher2.name); teacher2.age = teacher.age; teacher2.sex = teacher.sex; teacher2.name = (char *)malloc(strlen(teacher.name)+1); strcpy(teacher2.name,teacher.name); strcpy(teacher2.name,"Lee"); printf("Name: %s\n",teacher.name); printf("Sex: %c\n",teacher.sex); printf("Age: %d\n",teacher.age); printf("Name: %s\n",teacher2.name); printf("Sex: %c\n",teacher2.sex); printf("Age: %d\n",teacher2.age); free(teacher.name); free(teacher2.name); }
구조체 #include <stdio.h> struct man { char * name; char sex; int age; }; void disp1(struct man stud); void disp2(struct man * stud); main() { struct man student = {"Kim Chul Soo",'m',20}; disp1(student); disp2(&student); } void disp1(struct man stud) { printf("%s : %c : %d\n",stud.name,stud.sex,stud.age); } void disp2(struct man * stud) { printf("%s : %c : %d\n",stud->name,stud->sex,stud->age); } • 함수의 인수
#include <stdio.h> #include <string.h> struct man { char name[10]; char sex; int age; }; struct man setstud(char name[],char sex,int age); struct man clrstud1(); void clrstud2(struct man * pstud); void disp(struct man stud); main() { struct man student; student = setstud("Kim",'m',20); disp(student); student = clrstud1(); disp(student); student = setstud("Lee",'f',19); disp(student); clrstud2(&student); disp(student); } struct man setstud(char name[],char sex,int age) { struct man dt; strcpy (dt.name,name); dt.sex = sex; dt.age = age; return dt; } struct man clrstud1() { struct man dt; strcpy(dt.name,""); dt.sex = 0; dt.age = 0; return dt; } void clrstud2(struct man * pstud) { strcpy(pstud->name,""); pstud->sex = 0; pstud->age = 0; } void disp(struct man stud) { printf("%s : %c : %d\n",stud.name,stud.sex,stud.age); }
제3장 C++ & OOP
C++와 객체 지향 프로그래밍 • 객체지향의 특징 • 1. 캡슐화 (Encapsulation)와 데이터 숨김(data hinding) • C++는 클래스를 통해서 지원한다. • 사용자는 객체가 내부적으로 동작하는 방법에 관해서는 알거나 신경 쓸 필요가 없다. • 사용자는 클래스의 함수 이름과 Parameter의 형식만 알면 된다. • 2. 상속과 재사용 • C++는 상속을 통하여 재사용을 지원한다. • 3. 다형성 • 같은 부모로부터 상속 받은 어떤 함수가 상속 받은 Class의 특징에 따라서 다르게 행동하는 것