diff --git a/README.md b/README.md index 8e25079f196e1d1c5a67191748b773f2ec918e57..7389120482a3e8864370dd2b6891b670b5c58888 100644 --- a/README.md +++ b/README.md @@ -226,3 +226,735 @@ * ex) cat hello.c hello.cpp 1> out.txt 2> err.txt (에러를 저장하려면 2>을 사용해야함.) * '>>': 명령의 결과를 파일에 추가. (기존의 것들이 삭제되지 않음.) + +## Lecture 03 + +### Linux command + +1. which + * 파일의 위치를 출력하는 명령어. +1. grep + * 입력으로 전달된 파일의 내용에서 특정 문자열을 찾고자할 때 사용하는 명령어. +1. tee + * 입력한 내용을 화면에 출력하는 동시에 파일에 저장 해주는 명령어. stdin을 받아서 stdout과 하나 이상의 파일에 그 입력을 출력. + + ``` + cp ~hwan/.profile ~hwan/.bashrc ~hwan/.bash_logout ~ + source .profile + ``` + 교수님 코드를 카피하여 프롬프트가 초록색이 됨. 또한 path에 .이 추가되어 a.out만 입력해도 실행됨. + + +### md 사용법 +* 제목: # +* 부제목 : ## -> 6개까지 사용 가능. +* *은 리스트를 만들 때 유용, Tab을 써서 구분 +* br을 통해 줄 구분. +* 1.을 통해 번호를 매길 수 있으며, 1만 써도 자동으로 번호가 카운트. tab을 하면 다른 리스트로 분류되어 숫자가 리카운트. +* 순수하게 1.을 쓰고 싶다면 1\. 라고 입력하면 됨. +* ** ** 사이에 글자를 넣으면 bold, * * 사이에 넣으면 이태리체 +* 글자 끝에 #을 넣어 줄 구분. + +### git command +* git clone https://git.ajou.ac.kr/Hyeonuk/pcc000.git + * 해당 git 사이트에 있는 소스코드를 복제하여 내 컴퓨터에 가져옴. +* git pull + * 수정된 소스를 저장소로부터 가져오는 명령어. +* git add + * 작업 디렉토리(working directory) 상의 변경 내용을 스테이징 영역(staging area)에 추가하기 위해서 사용.<br>다음 변경(commit)을 기록할 때까지 + 변경분을 모아놓기 위해서 사용. +* git commit -m "" + * commit은 파일 및 폴더의 추가/변경 사항들에 대해 기록을 하는 것, 작업공간 안에 있는 모든 파일과 파일의 데이터를 사진 찍듯이 복사해서 저장소에 보존. + 즉, 커밋은 작업공간의 어떤 시점의 스냅샷. + * -m을 통해 editor 실행X. + * "" 사이에 말을 추가 가능. +* git config + * 원격 저장소로 데이터를 넘길때 커밋한 사람이 누구며, 어떠한 사람인지 남길 필요가 있다. 이런 인증에 대한 부분을 git config 명령어로 설정. +* git push + * 현재 프로젝트의 커밋된(HEAD) 내용을 원격 저장소로 내보내는 명령어입니다. +* git mv + * git에 있는 파일의 이름을 바꾸는 명령어. +* git rm + * 로컬 디렉토리와 git 저장소 모두에서 파일을 삭제. + + +### fork, branch 차이점 +* fork는 다른 사람의 Github repository에서 내가 어떤 부분을 수정하거나 추가 기능을 넣고 싶을 때 해당 respository를 내 Github repository로 그대로 복제하는 기능이다. <br> +즉 Repository에 권한이 없는 사용자가 저장소를 fork하고 fork한 자신의 저장소에 변경 사항을 적용한 후 Push한다. 이 후 원래 저장소(original repository)에 내 저장소에 있는 브랜치를 Pull Request 한다. 내가 만든 코드가 ok되면 해당 저장소에 Merge 된다. <br> +-> 또 다른 프로젝트를 만들 때 사용. +* 은 특정 repository를 내 local machine에 복사하여 새로운 저장소를 만든다. clone한 원본 repository를 remote 저장소 origin으로 가지고 있다. 권한이 없는 경우 해당 저장소로 push 하지 못한다. <br> +->소규모 팀에서 활용 가능한 예, 프로젝트를 수정할 때 사용. + +## Lecture 04 + +### understanding redirection +* Basic + * < = 0<, << = 0<<, > = 1>, >> = 1>>, 2> = 2>> + * &>, 2>&1, &>> + * <<< +* Position of redirection + * echo hello > /tmp/out - hello를 tmp/out에 저장. <br> + = echo > /tmp/out hello <br> + * echo hell0 >&2 - stdout, stderr 둘다 내보낸다. <br> + = echo >&2 hello + * read -r line < file - file의 한 줄을 읽는다. <br> + = < file read -r line +* 단축코드 + * mycomn > outfile 2>&1 을 줄여서 mycomn &> outfile + * mycomn >> outfile 2>&1 을 줄여서 mycomn &>> outfile + * mycomn1 2>&1 | mycomm2 을 줄여서 mycomm1 |& mycomm2 + * https://mug896.github.io/bash-shell/redirections.html +### Here document, Here String +* 0<<, << + * 임시 파일을 만들어 stdin으로 연결. <br> + ``` + $cat << EOF + > "200" + > EOF + "200" + ``` +* <<< (bash only) + * string을 stdin 입력으로 연결. + ``` + $ cat <<< * + * + ``` +### Pipe Order of execution +* 실행의 순서는? + * $ cmd1 | cmd2 + * cmd1과 cmd2는 동시에 병렬로 실행된다. + * cmd1이 cmd2보다 빠르면 파이프에 write은 블록되고 더 이상 진행되지 않는다. + * cmd2가 cmd1 보다 빠르면 파이프로부터의 read는 블록된다. + * cmd1이 먼저 종료하면 파이프는 close 되고 cmd2는 End-Of-File 로 인식해 종료한다. + * cmd2가 먼저 종료하면 파이프는 close 되고 cmd1은 다음번 write에 SIGPIPE 신호를 받게되고 종료된다. +### Named pipe +* pipe는 자동으로 생성/소멸 +* Named pipe + * mkfifo 명령으로 생성 - 파일처럼 생성됨. + * redirection으로 sending +* 읽는 상대편이 없으면 Block 된다. +* Buffer Control이 필요. + +### linux command +* ????* + * 이름이 4글자 이상인 파일들을 모두 보여주는 명령어. +* echo [abc]* + * 이름이 a, b, c로 시작하는 파일들을 모두 보여주는 명령어. +* echo [a-q]* + * 알파벳 사전순으로 a~q까지의 알파벳으로 시작되는 파일을 모두 보여주는 명령어. + +### Type Basic +*Standard signed integer type + * signed char, short int, int, long int, long long int +* Unsigned + * Unsigned ... +* floating type + * flout, double, (long double) +* Definition in standard + * char - large enough to store any execution character set. + * floating - The set of values of the type float is a subset of the set of values of the type double; + the set of values of the type double is a subset of the set of values of the type long double. + * _complex + * _Bool - can store 0, 1 + +### Negative integer +* 3 Well know methods to represent signed integer + * the corresponding value with sign bit 0 is negated (sign and magnitude); + * the sign bit has the value - (2M)(two's complement); + * the sign bit has the value (2M-1)(one's complement). +* Which method is used in C Language? + * All three are possible. + * 근데 대부분은 2's complement를 사용. + * 2'complement + * 1의 보수(~)를 구한 후, 가장 낮은 비트에 +1 + +### Unsigned int +* un-sign-ed 라는 것은 결국 "부호가 없다"는 뜻이고, 그래서 항상 플러스 값만 가짐. +* %u를 통해 출력. + +### 시프트 연산 +* '>>': /2 +* '<<': *2 + +### signed int 와 unsigned int에서 시프트 연산의 차이 +``` +int in_a, in_b; +fscanf(stdint, "%d", &in_a); +in_b = in_a >> 2; +``` +signed int의 경우 a에 음수 값을 넣고 오른쪽으로 두칸 이동할 때 남는 공간에 1이 채워진다. 양수 값일 경우 0이 채워짐. +``` +unsigned int in_a, in_b; +fscanf(stdint, "%d", &in_a); +in_b = in_a >> 2; +``` +unsigned int의 경우 a에 음수 값을 넣고 오른쪽으로 두 칸 이동할 때 남는 공간에 0이 채워짐. 양수 값일 경우 1이 채워짐. + +나누기 연산에서도 마찬가지이다. + +## Lecture 5 + +### Linux command + +1. more + * 파일을 화면 단위로 출력해주는 명령어. + * Enter : 다음 한 줄 출력 + * Space Bar or z : 다음 한 페이지 출력 + * q,Q : 종료 +1. less + * 파일 내용을 페이지 단위로 보여주는 명령어. + * more 명령어의 기능을 줄인 명령어. + +### signed와 unsigned의 fscanf 입력 +``` +#include <stdio.h> +int main() +{ + signed int siA; + unsigned int unA; + signed int sumS; + unsigned int sumU; + + fscanf(stdin, "%d", &siA); + fprintf(stdout, "Signed Inteager : %d\n", siA); + unA = siA; + fprintf(stdout, "Unsigned Inteager : %u\n", unA); + fprintf(stdout, "Unsigned Inteager percent d : %d\n", unA); + fprintf(stdout, "Signed Inteager percent d : %u\n", siA); + + sumS = siA + unA; + sumU = siA + unA; + fprintf(stdout, "sumS %%d %d\n", sumS); + fprintf(stdout, "sumS %%u %u\n", sumS); + fprintf(stdout, "sumS %%d %d\n", sumU); + fprintf(stdout, "sumS %%u %u\n", sumU); +``` + + <br> +위 사진은 코드를 실행하고 100, -100을 넣은 결과이다. +unsigned int로 선언했더라도 출력시 %d로 받는다면 signed 형태로 받아서 나온다. 그래서 -100을 넣어도 -200이라는 sumS, sumU 출력값이 나온다.<br> +<br> +위 사진은 코드를 실행하고 4294967200을 넣은 결과이다. <br> +근데 결과를 보면 Signed int가 -96이 나온 것을 볼 수 있다. 오버플로우가 일어나지 않은 이유가 무엇일까? +우선 4294967200이 2진수로 변환하면 11111111111111111111111110100000이 된다. 그리고 scanf에 %d가 들어가면 내부적으로 strtol이 호출되는데, +이것은 변환대상이 최대값을 넘어갈 경우 long_max(0x7fffffff)을 반환한다. fscanf도 마찬가지로 내부에서 strtol 함수를 호출해서 +오버플로우 현상이 일어나 입력값을 2147483647로 구겨넣는다. 하지만 64 bit os의 최대값은 0x7fffffffffffffff임으로 오버플로우가 일어나지 않는다. +그러므로 2진수로 변환된 11111111111111111111111110100000이 그대로 들어간다. 이 숫자는 96의 2의 보수이다. <br> +반면 unsigned int는 정상 출력이 되는 것을 확인 할 수 있는데 이는 unsigned int의 범위가 0~4294967295까지이기 때문이다. + +### Count number of 1 (binary) +``` +#include <stdio.h> + +//Count number of 1 (binary) +int count_one(int in_a) +{ + int i, count = 0; + for(i = 31; i>=0; i--) + { + if((in_a>>i) & 1) + count++; + count += (in_a>>i)&1; + } + return count; +} + +int main() +{ + int i; + unsigned int in_a; + fscanf(stdin, "%u", &in_a); + fprintf(stdout, "%u \t: ", in_a); + for(i=31; i>=0; i--) + { + fprintf(stdout, "%d", ((in_a>>i) & 1)); + if(i % 4==0) + { + fprintf(stdout, " "); + } + } + fprintf(stdout,": %d \n", count_one(in_a)); +} +``` + +하지만 코드를 좀 더 빠르게 하기 위해 +``` +int count_one(int in_a) +{ + int i=32, count = 0; + while (i>0) + { + count += (in_a>>i) & 1; + i--; + } + return count; +} +``` +위 사진과 같이 함수를 수정하여 나타낼 수 있다. if문은 operation이 오래걸리기 때문이다. + + <br> +사진과 같이 10과 -1을 넣었을 때 결과값을 확인할 수 있다. 이때 -1을 넣었을 때는 in_a의 출력값이 4294967295가 나오는 이유는 +in_a가 unsigned int로 선언되어있기에 -1의 2진수가 그대로 들어갔고 이것이 오버플로우 없이 그대로 출력되었기 때문이다. + +### The basic memory model in C +* automatic variable (자동변수) + * Declare a variable on first unsigned + * remove when it goes out of scope. +# +* static variable (정적변수) + * exit in the same place throughout the life of the program. + * Array sizes are fixed at startup, but values can change + * Data is initialized before main starts, -and thus any initializations have to be done with constants that require no calculations. + * Variables declared outside of functions (in file scope) and inside functions with the static keyword are static. + * If you forget to initialize a static variable, it is initialized to all zeros (or NULL). +# +* Manual + * The manual type involves malloc and free, only type of memory where arrays can be resized after declaration. +# +* const + * constant의 약자로 "변함없는" 이란 뜻으로 변수 앞에 붙이면 값을 변경하지 못하도록 하며, 해당 변수를 상수로 취급하게 된다. + +## Lecture 06 + +### Linux command +* clear + * 터미널의 텍스트 화면을 깨끗이 지우는 명령어 +* alias + * 자주 사용하는 명령어를 특정 문자로 입력해두고 간편하게 사용하기 위한 것으로 command alias라고 한다. 복잡한 명령어와 옵션을 짧은 문자열로 바꿔주는 명령어 + * alias -p를 통해 확인 가능. + * unalias를 통해 해제 할 수 있다. unalias -a은 모든 alias 설정을 삭제. + * alias 설정한 것을 사용하고 싶지 않을 때는 \ls 처럼 \를 붙여 사용. +* cc && a.out + * 컴파일 후 에러가 없을 경우 a.out을 실행하는 명령어. +* cc ; a.out + * 컴파일 후 a.out을 실행하는 명령어. 이때 컴파일 에러가 발생하면 가장 최근에 컴파일 성공한 a.out의 결과를 출력. +* cc || echo "Errrr" + * 컴파일 에러가 날 경우 echo의 결과를 출력해주는 명령어. + +### Pointer Basic +* &val - val의 주소. + * %lld로 받음. +* *ptr - val 주소의 값. + * *&a는 a가 가리키는 주소의 값. + + +* increment + * int *a; // a++ increment by 4 + * long long *b // b++ increment by 8 + * void *c // c++ increment by 1 + + +### int an_array[ ] vs int *a_pointer +* int an_anrray[32]; (int로 저장되서 4 byte, an_array 자체는 8byte 공간에 저장.) + * Program will do; + * set aside a space on the stack big enough for 32 integers, + * declare that an_array is a pointer, and + * bind that pointer to point to the newly allocated space. +* int *a_pointer; + * Just pointer; + * a_pointer = malloc(32*4); + +``` +#include <stdio.h> + +void add(int *a, int *b, int *c) +{ + *c = *a + *b; +} + +int main() +{ + const int a = 100; + int b = 200; + const int c = 999; + + fprintf(stdout, "%d : %lld\n", a, &a); + fprintf(stdout, "%d : %lld\n", b, &b); + add(&a,&b,&c); //2 +// c = a+b; //1 + fprintf(stdout, "%d : %lld\n", c, &c); + int d=999; + fprintf(stdout, "%d :%lld %lld\n", d, ((void *)(&d))+1, &d+1); // 3 + } + +``` +위 코드의 경우 c를 1번과 같이 구할 경우와 2번으로 구하는 경우가 다르다. add함수로 갈 경우 c의 주소의 값을 수정하는 것이기 때문에 오류가 발생하지 않지만 1처럼 그냥 수정하려고 한다면 const int이기 때문에 오류가 발생한다. 3의 fprintf에서 자료형을 int에서 void로 바꾸어주는데 이 때문에 메모리 크기가 4에서 1로 바뀌고 &c+1 은 메모리 주소가 int와 다르게 1만 증가하게 된다.<br> +또한 add 함수에서 *b = *(a+1) 와 같이 나타낼 수 있는 것은 이것들이 메모리 주소 형태로 들어왔기 때문에 가능하다. + +``` +#include <stdio.h> + +int sumArray3(int a[3], int sum) +{ + sum = *a; + a++; + sum += *a; + a++; + sum += *a; + fprintf(stdout, "%d : %lld %llx\n", sum, &sum, &sum); + return a[3]; +} + +int main() +{ + int a=100; + int b = 200; + int c = 999; + int arr[4] = {100,200,300,400}; + int *parr; + parr = arr; + parr++; + fprintf(stdout, "%d : %lld %lld\n", *parr, parr, arr); + + c = sumArray3(arr, b); + + fprintf(stdout, "%d : %lld %llx\n", b, &b, &b); + fprintf(stdout, "%d : %lld %llx\n", *arr, *arr, *arr); + fprintf(stdout, "%d : %lld %llx\n", &arr, &arr, &arr); + fprintf(stdout, "%d : %lld %llx\n", arr[2], &arr[2], &arr[2]); + fprintf(stdout, "%d : %lld %llx\n", arr[3], &arr[3], &arr[3]); + fprintf(stdout, "%d : %lld %llx\n", arr[4000], &arr[4000], &arr[4000]); + +} + +``` +위 코드를 처럼 arr 배열을 선언하여 출력하면 <br> + +* 위 사진과 같은 결과를 얻을 수 있다. 사진에서는 arr가 각각 %d, %lld로 출력될 때 각각 값이 200, 140722121785492이 출력된다. +* 또한 바로 밑에 arr[2]가 출력된 것을 보면 주소가 8 증가한 것으로 보아 int arr로 선언되었기에 메모리 값이 4씩 증가하는 것이 확인된다. +* main함수에서 sumArray3 함수로 arr, b를 보내지만 b의 값은 바뀌지 않고 sum이라는 변수가 하나 생기게 된다. 또한, a의 주소 변경을 통해 값을 바꿀 수 있는 것을 sum += *a; a++;을 통해 알 수 있다. +# + * **배열은 Call by reference, int는 Call by value로 전달되었다.** + * Call by reference와 Call by value는 각각의 특징이 있는데, Call by value의 경우 데이터(값)을 복사해서 함수로 전달하기 때문에 <br> + 원본의 데이터(값)가 변경 될 가능성이 없지만, 인자를 넘겨줄 때마다 메모리의 공간을 할당하기 때문에 메모리 공간을 좀 더 잡아먹게 된다. <br> + Call by reference의 경우 메모리 공간 할당의 문제를 벗어나게 되었지만 원본의 데이터(값)를 훼손할 수 있다는 문제점이 있다. <br> + 그러므로 상황에 맞게 적절히 사용해야겠다고 생각한다. +# +* 마지막으로 arr은 const이기 때문에 arr++;처럼 직접 바꾸려고 하면 에러가 발생한다. 그러므로 int *parr과 같이 따로 포인터를 만들어서 해야된다. + +### Pointer / Address + +* int const A constant integer +* int const * A (variable) pointer to a constant integer +* int * const A constant pointer to a (variable) integer +* int * const * A pointer to a constant pointer to an integer +* int const * * A pointer to a pointer to a constant integer +* int const * const * A pointer to a constant pointer to a constant integer + +## Lecture 07 + +### int const * 와 int * const의 차이 + ``` + #include <stdio.h> + void add(int *a, int *b, int *c) + { + *c = *a + *b; + } + int main() + { + int const a = 100; + int b = 200; + int c = 9999; + int const * p = &a; + fprintf(stdout, "a, b ,c : %d %d %d\n", p, b, c); + p = &b; + fprintf(stdout, "a, b ,c : %d %d %d\n", p, b, c); + } +``` +* int const * 는 const int형을 가리키는 포인터로 포인터 값은 변경이 가능하므로 다른 것을 가리킬 수 있으나 내부의 int 값은 const로 선언되어 변경이 불가능하다. + +* int* const 는 const 포인터가 int형을 가리키고 있으므로 포인터의 값은 변경이 불가능하고 내부의 int형으로 표현된 값은 변경이 가능하다. + +### 함수의 Pointer + +``` +#include <stdio.h> +#define FN_ADD 0 +#define FN_SUB 1 +#define FN_MUL 2 +#define FN_DIV 3 + +void add(int *a, int *b, int *c) +{ *c = *a + *b; } + +void sub(int *a, int *b, int *c) +{ *c = *a - *b; } + +void mul(int *a, int *b, int *c) +{ *c = (*a) * (*b); } + +void div(int *a, int *b, int *c) +{ *c = (*a) / (*b); } + +int main() +{ + int a, b, c; + char ch; + int op = FN_ADD; // default is add + + scanf("%d %c %d", &a, &ch, &b); + + void (*fp[4])(int *, int *, int *) = {add, sub, mul, div}; + switch (ch) + { + case '+': + op = FN_ADD; + break; + case '-': + op = FN_SUB; + break; + case '*': + op = FN_MUL; + break; + case '/': + op = FN_DIV; + break; + default : + op = FN_ADD; + break; + } + + fp[op](&a,&b,&c); + fprintf(stdout, "%d \n", c); + + fp[5](&a,&b,&c); + fprintf(stdout, "%d \n", c); + + // int const * p = &a; + // int * const q = &a; +} +``` +* 함수의 주소를 저장했다가 해당 주소의 함수를 호출할 때 사용한다. + +* void (*fp)와 같이 선언한다. + +* 배열은 (*fp[4])와 같이 선언한다. + +* #define과 const의 차이점 + * #은 preprocessor + * const는 타입을 가지므로 표현 범위와 구조에 대해 명확하게 된다. + * const에는 메모리가 할당된다. 컴파일러로 하여금 그 영역에 덮어쓰는 작업을 막도록 감시하게 해 줄 뿐이지 + 주소를 직접 건드리면 const의 값 마저 변경될 수 있다. + +### gcc compile options + +### gcc compile - for multiple file +* extern + * 외부 파일에서 선언된 변수를 사용. +<br> +<br> +* 위 사진과 같이 코드를 짜고 gcc main.c func.c를 하게 되면 우선 #(preprocessing)이 일어나 stdio 와 func.h를 불러온다. 그래서 main함수에서 DF == ((a)*(a))가 되고 func.h에 있는 extern에 의해서 func.c에 있는 func1이 호출된다. 만약 extern이 없으면 func.c에 있는 함수를 사용할 수 없다. +* cc -c main.c + * main.c를 main.o로 만들어주는 명령어. +* .o 파일 + * c 소스 프로그램을 컴파일 할 때 생기는 목적 코드 파일. 기계어로 이루어져있다. + * cc main.o func.o를 하여도 정상적으로 a.out이 생성된다. 왜냐하면 .o에서 링크 단계를 거치면 a.out이 생성되는 것이기 때문이다. + +### C Preprocessor (CPP) +* Macro Processor for C, C++, Objective-C + * Include head files + * Define macro + * Conditional Compliation + * Line Control + +### CPP - include file +* #include file as text + * #include <stdio.h> or "file.h" +* gcc Option - I + * Include location - ./usr/include/ + * Default include location +* Prevent multiple include + * #pragma once + * #ifndef _MATH_ <br>#include <math.h> + <br>#endif + +### CPP - Conditional Compilation +* #if, #ifdef, #ifndef, #elif, #else, #endif + +* Select code with condtion +``` + * #ifdef _VERSION_<br> + #if _VERSION_ >= 3<br> + printf("Version is greater or equal than 3\n"); + #elif _VERSTION_ == 2 + #error VERSTION 2 IS NOT SUPPORTED + #endif + #endif // idfef _VERSION_ +``` +### Marco Definition +<br> + +### 과제: if문을 이용하여 조건부 컴파일하기 +``` +//func.c + +#include "func.h" + +extern int fun1(int x); +extern int fun2(int x); + +#if __FUNC_ == 0 +int func1(int a) +{ + return(a*10); +} + +#else + +int func1(int a) +{ + return DF(a+1)*20; +} + +#endif + +int func2(int a) +{ + return DF(a+1)*10; +} + +``` + +``` +// func.h + +#ifndef __FUNC_ + +#define __FUNC_ 0 + +#if FUNCTION_NEGATIVE == 1 +#define DF(a) (-(a)*(a)) +#else +#define DF(a) ((a)*(a)) +#endif + +extern int func1(int x); +extern int func2(int x); + +#endif +``` +``` +// main.c + +#include <stdio.h> +#define FUNCTION_NEGATIVE 1 +#include "func.h" + +int main() +{ + printf("Func1 %d %d\n", func1(100), DF(10)); + + printf("Func2 %d %d\n", func2(100), DF(10)); + +} +``` +* #if와 endif는 항상 짝을 이루어야한다. +* func.h에서 extern을 통해 func.c에 있는 func1, func2을 사용한다. +* func.c에서 ```#if __FUNC_ == 0```과 #else를 통해 0일 때는 두 종료의 func1 중에 하나를 선언, 그 외에는 func2를 선언한다. 이때 ```__FUNC_``` 을 0 이라고 정의했기 때문에 두 번째 func1은 컴파일 되지 않는다. +* main.c에서 fun1, fun2의 함수에 대입하여 결과값을 출력한다. + +### GCC Optimization +* -O0(기본값) + * 최적화를 수행하지 않는다. +* -O, -O1 + * 코드 크기와 실행 시간을 줄이는 것을 제외한 최적화는 실행하지 않는다. +* -O2 + * 메모리 공간과 속도를 희생하지 않는 범위내의 모든 최적화를 수행한다. (loop unrolling과 function inlining에 대한 최적화를 수행하지 않는다.) +* -O3 + * -O2 최적화에 인라인 함수와 레지스터에 대한 최적화를 추가로 수행한다. +* -Os + * -O2 최적화 기능을 사용하지만, 코드 크기를 증가시키는 최적화는 생략한다. + + +### C Compile and Execution + + +### gcc option +* gcc -o (실행파일명) (파일명) + * 실행파일명으로 실행파일을 만든다. +* gcc -E + * 전처리 과정의 결과를 화면에 보이는 옵션 (전처리과정 중 발생한 오류를 검증) +* gcc -S + * cc1으로 전처리된 파일을 어셈블리 파일로 컴파일까지만 수행하고 멈춘다. (*.s) + +* gcc -c + * as에 의한 어셈블까지만 수행하고 링크는 수행하지 않는다. 오브젝트 파일 생성 (*.o) + +### CPP processing + + +### Macro Definition (1) + + +### Macro Definition (2) + + +### Macro Definition (3) - Function like Macro +* ``` + #define min (X, Y) ((X) < (Y) ? (X) : (Y)) + x = min(a,b); -> ((a) < (b) ? (a) : (b)); + y = min(1,2); -> ((1) < (2) ? (1) : (2)); + z = min(a + 28, *p) -> z = ((a+28) < (*p) ? (a+28) : (*p)); + if문 보다 성능이 좋다. + + * BAD Examples + #define f(a) a*a <br> + b = f(20+13) // 20 + 13 * 20 + 13 + * Omit parameter <br> +  + + + +* ```__LINE__```은 몇 번째 라인인지 알려주며, 재정의 할 경우 그 밑줄부터 다시 카운트한다. +* ```__FILE__```은 파일명을 출력한다. 해당 파일의 경우 이름이 hello.c이기 때문에 hello.c를 출력한다. +* &a와 &b가 long long으로 정의되면 %lld로 출력될 때 warning이 발생하지 않는다. +* ERR_DATA를 1000이라고 했기 때문에 if 문에 걸리지 않고 else로 넘어가 waring문을 띄어준다. + +### cc 옵션 +* cc -g + * gdb에게 제공하는 정보를 바이너리에 삽입한다. + * -g 옵션을 사용하지 않고 gdb로 디버깅하면, 역어셈 → 어셈블리 코드로만 디버깅 가능하다. + +* cc -pg + * 프로파일을 위한 코드를 삽입한다. + * -pg 옵션으로 컴파일 → gmon.out(프로파일 정보) → gprof로 gmon.out 파일 분석 + +### 복습 +* a.out &> output.txt의 의미 = a.out의 stdout과 stderr 둘 다 output.txt로 redirection 한다. + +### Linux Command +* ps : 현재 실행중인 프로세스(job) 목록과 상태를 보여준다. +# +* ps -l : 긴 포맷으로 보여준다. +# +* fg : background에서 실행되고 있는 작업을 foreground로 옮기는 명령어 +# +* bg : foreground에서 실행되고 있는 작업을 background로 옮기는 명령어 + +### vi가 background로 돌 수 없는 이유 +* vi 에디터는 stdin에서 입력을 받는다. 그러면 vi를 백그라운드로 돌리고 배쉬 작업을 하면(배쉬 작업도 stdin에서 명령을 받는다.) 이때 <br> +사용자가 입력한 명령은 vi로 가는지 bash로 가는지 알 수 없다. 따라서 stdin을 쓰는 명령어나 프로그램, 앱은 background로 돌 수 없다. <br> +stdin을 사용하는 프로세스가 만약 background로 실행되고 있는 와중에 scanf를 만나면 그 자리에서 멈춘다. + +## Lecture 14 + +* 버퍼 : 하나의 장치에서 다른 장치로 데이터를 전송할 경우에 양자간의 데이터의 전송속도나 처리속도의 차를 보상하여 <br> +양호하게 결합할 목적으로 사용하는 기억영역을 버퍼 또는 버퍼 에어리어라고 한다. 보통 중앙처리장치와 단말이나 다른 입출력장치사이의 <br> +데이터 송수신에는 입출력 영역으로서 버퍼를 필요로 한다. <br> + + +* 가장 중요한 3가지 표준 버퍼 : stdin, stdout, stderr + +* POSIX (Portable Operating System Interface) : 다른 운영체제들 사이에서 호환성을 위해 IEEE에서 만든 표준이다. <br> + +* fifo (First in First Out) : 대기행렬에서의 선입선출 제어 방식이다. 복수의 신호 혹은 job이 처리대기로 되어 있을 경우 <br> +처리의 우선순위를 붙이지 않고 먼저 도착한 순서로 처리하는 방식이다. + +* stack : 스택은 컴퓨터에서 사용되는 기본 데이터 구조 중 하나로 데이터를 후입선출 구조로 유지하는 추상 데이터형을 말한다. + +### Understanding Buffer and stream +* buffer control + * no + * line + * block <br> +