성적처리 프로그램 예제 소스
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define averageScore 70.0F
typedef struct _student {
char name[10];
char isPass[10];
int korScore, engScore, sum;
double average;
} student;
int main(void)
{
int index = 0, num = 0;
printf("몇 명의 학생 입력? \t");
scanf("%d", &num);
student *ptr[3] = {NULL};// 3개의 student형 포인터를 담는 배열 , 초기화 방법에 유의 {NULL}
for (index = 0 ; index < num; index++) {
ptr[index] = (student *)malloc(sizeof(student));
printf("학생의 성명만 입력하세요: ");
scanf("%s", ptr[index]->name);
printf("국어, 영어 점수를 입력하세요: ");
scanf("%d, %d", &ptr[index]->korScore, &ptr[index]->engScore);
ptr[index]->sum = ptr[index]->korScore + ptr[index]->engScore;
ptr[index]->average = (double)ptr[index]->sum / 2.0;
if (ptr[index]->average >= averageScore) {
strcpy(ptr[index]->isPass, "Pass");
} else {
strcpy(ptr[index]->isPass, "Fail");
}
}
for(index = 0; index < num; index++) {
printf("학생명 국어점수 영어점수 총점 평균\t평가\n");
printf("%s %d\t %d\t %d\t%f%s\n", ptr[index]->name, ptr[index]->korScore, ptr[index]->engScore, ptr[index]->sum, ptr[index]->average, ptr[index]->isPass);
free(ptr[index]);
ptr[index]= NULL;
}
return 0;
}
해당 코드를 보면서 아래 Memory Map을 같이 보라
약간의 비약이 있지만...
만약 컴퓨터 프로그램이
모든 명령어 하나당 하나씩 메모리에 적재하고 빼는 방식의 구조로 되어있었다면
Overhead가 커져서 비효율적이다.
따라서 관련된 명령어들을 한꺼번에 복사하여 저장하는 방식으로 메모리를 관리한다.
- e.g. Paging & Segment 기법
메모리 영역을 다음과 같이 총 4구역으로 나눌 수 있다.
1. Code Segment
읽기만 할 수 있는 영역으로
프로그램 실행 도중에 더 이상 명령어나 데이터를 쓸 수 없는 '상수'를 올려놓고
보통의 경우 함수 하나당 한개의 Code Segment를 할당한다.
2. Data Segment
리터럴 상수, 문자열 리터럴을 저장한다.
C에서 '문자열'이라 함은 끝에 '\0' null character를 포함한다.
3. Heap Segment
프로그래머가 직접 명시하여 할당하는 동적 관리 영역이다.
C에서 malloc으로 할당한 영역으로
Low Address -> High Address로 올라간다.
※ 예제에서는 ptr[index]를 통해 구조체 배열이 Heap 영역에 할당되었다.
할당, 해제 모두 프로그래머가 명시적으로 하는 Segment로
free(주소)를 함으로써 Heap영역에 할당했던 부분을 명시적으로 해제해야
Memory leak을 방지할 수 있다.
4. Stack Segment
보통 {} 중괄호 블록단위로 적재되고 해제되는 영역,
High Address -> Low Address로 쌓여간다.
printf, scanf literal 상수를 갖는 함수 모두
첫번째 인자는 무조건 Data Segement에 할당된 배열의 시작주소가 저장된다.
ex) printf("%d, %d, %s", &num, &korScore, name)이라고 치면
변수 갯수인 3개가 아니라
Data segment영역의 시작 주소를 가리킬 포인터를 포함해 총 4칸이 할당되어야한다.
main 함수 내에서 호출된 함수는 Stack 영역에 할당되었다가
마지막 '}'을 만나면 해제된다.
R-Value (식의 우변) +나 / 연산은
CPU의 'Regeister'에 의해 이뤄지고
Register중에 AC (Accumulator) 누산기에 값이 임시저장되고
AC에 담긴 결과값만 Main Memory(L-Value, 식의 좌변)에 저장한다.
(MAR, MBR, IR, AC 등등.. Computer Structure 시간에 배운..)
※ 주의
사실 Library Function (ex. printf , scanf 등) 과같은 함수 또한
Code, Stack segment에 작도했지만
평소에 프로그래밍 하면서 라이브러리 함수가 어떻게 작동하는지 생각할 필요는 없다.
사용하고자 하는 함수의 Interface, Input, Output, Function만 알면된다.
+
코드 맨 마지막에 맨날 오는
return 0; 같은 코드가 의미하는 것은
운영체제에게 반환할 값이다.
즉 0이라는 값이 레지스터에 복사되어 운영체제에 반환되고
Code Segment의 Main함수가 해제됨으로써 프로그램이 종료되는 것이다.
'C > C' 카테고리의 다른 글
main 함수 (feat. argc, argv) (0) | 2019.11.10 |
---|---|
파일 입출력 fopen (0) | 2019.11.10 |
2차원 배열 이해 (0) | 2019.09.29 |
배열 초기화 사소한 Tip (0) | 2019.09.26 |
성적 처리 프로그램 (분석->설계->구현) (0) | 2019.09.20 |