https://cs50.harvard.edu/x/2023/weeks/2/
- tedious 지루한
- exploit 이용하다
- obnoxious 불쾌한
- stipulate -을 규정하다
- cipher 암호
code hello.c (생성)
make hello (컴파일)
./hello (실행)
컴파일러 C언어 -> clang
원레 clang -o hello.c hello -lcs50 이지만, 줄여서 make hello 로 표현한다.
컴파일 과정 4단계
preprocessing
/usr/include. 에 preinstall된 라이브러리 호출(#include <stdio.h> 와 같이 #으로 지명된것만)
compiling
assembly language (기계언어(바이너리코드)에 가깝지만 숫자로 된 명령어를 영단어로 바꿔놓은 형태)
assembling
00101010 바이너리코드로 바꿔줌
linking
기계언어로 바뀐 라이브러리(stdio.h)와 메인코드파일(hello.c)을 서로 링크시킴
decompiling
모든 변수명등이 제거되고, 실제 실행되는 바이너리만 남아있으므로 매우 어려움.
debug
printf 활용해서 어떻게 작동되는지 시각적으로 확인하며 버그 확인
vscode에 내장되어있음.
debug50 ./hello
왼쪽에 빨간 동그라미 클릭하면 거기서 멈추고, step by step 으로 실행되는거 확인 가능.
rubber duck
과정을 말로 설명하면서 잘못된 로직을 찾아내는 것
C언어의 datatype
bool 1byte
int 4bytes
long 8bytes
float 4bytes
double 8bytes
char 1byte
string ?bytes
string 은 결국 char이 모여있는 array이다.
hi! 의 경우
h i ! \0(null이며, 해당 string array가 끝남을 알림)
따라서 아래처럼 출력이 가능하다.
#include <cs50.h>
#include <stdio.h>
int main (void)
{
string s = "HI!";
printf("%i %i %i %i \n", s[0], s[1], s[2], s[3]);
}
$ make hi
$ ./hi
72 73 33 0
(72,73,33,0 은 각 character 의 ascii 번호이다.)
마지막에 \0 으로 끝남을 알려주므로,
string의 길이를 구하는 것은 아래와 같이 가능하다.
(C언어에서 string을 제외한 array는 길이는 길이 값이 미리 선언이 되어있지 않는 한 구하는것이 매우 어렵다.)
int main(void)
{
string name = get_string "What's your name? ");
int n = 0;
while (name[n] != '\0'
{
n++;
}
printf("%i\n", n);
}
<string.h>라는 라이브러리도 있음 -> int n = strlen(name) 형식으로 사용
<ctype.h>
소문자-> 대문자 변환도 ascii 번호 기준, 32를 더하거나 빼는걸로 구현함.
#include <cs50.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
string s = get_string("Before: ");
printf("After: ");
for (int i = 0; i < strlen(s); i++)
{
if (s[i] >= 'a' && s[i] <= 'z')
{
printf("%c", s[i] - 32) ;
}
}
}
int main(void)
{
string s = get_string("Before: ");
printf("After: ");
for (int i = 0; i < strlen(s); i++)
//이것처럼 for loop내부, 특히 조건부분에 strlen을 계속 호출함.
{
printf ("%c", toupper(s[i]));
}
printf("\n");
}
//따라서 아래와 같이 바꿔야 효율적임(strlen은 바뀌지 않으므로 한번만 호출하도록)
int main(void)
{
string s = get_string("Before: ");
printf("After: ");
for lint i = 0, n = strlen(s); i < n; it+)
//이것처럼 바꾸면 더 효율적인 연산 가능함
{
printf ("%c", toupper(s[il));
}
printf("\n")
#include <cs50.h>
#include <stdio.h>
int main(int argc, string argv[]) //argc는 단어의 갯수(문장길이), argv는 단어[위치]
{
if (argc == 2)
{
printf ("hello, %s\n", argv [1]); //argv[0]는 프로그램 이름이 출력됨. [1]부터 시작.
}
else
{
printf("hello, world\n");
}
}
위와 같이 main함수 안에 저 변수를 넣으면, 터미널에서 프로그램을 불러오면서 바로 실행이 가능하다.
즉, 실행과 동시에 input값 입력이 가능.
./greet David 와 같은 형식으로 사용.
또한, argv[0]를 사용하면 이 출력이 어떤 코드 파일로 인한 출력인지 나오므로 가끔, 사용하기도 함.
int main (void)
int main (int argc, string argv[])
위 두가지가 알아둘 두가지 C언어 main 함수
exit status
C언어에서는 기본적으로 함수가 실행되면 return 0; 이 기본적으로 실행되고, 커맨드창에선 생략된다.
echo $? 으로 볼 수 있음.
return 1 와 같은 방식으로 수정도 가능함.
이 코드를 통해 작동여부 체크도 가능함.
echo$? : 마지막으로 종료된 명령어의 종료 상태를 말해주는데, 종료상태란 정상적인 종료0과 비정상적 종료인 0을 제외한 다른 값을 의미한다. (출처 https://kim-dragon.tistory.com/48)