[CS50] C언어

먼지·2022년 12월 14일
0

컴퓨터과학

목록 보기
2/2
post-thumbnail

1) C기초

핵심 단어

  • stdio.h
  • clang
  • 컴파일러

C언어

C는 아주 오래되고 전통적인 순수 텍스트 기반의 언어

#include <stdio.h>

int main(void)
{
    printf("hello, world\n");
}

int main(void) 는 스크래치의 "초록색 깃발을 클릭했을 때" 블록과 같은 역할을 함. 즉, '시작한다'의 의미를 갖고 있음. 앞으로 우리가 작성할 코드 모두는 이 int main(void) { }의 중괄호 사이에 작성

C에선 스크래치의 say라는 함수는 없음. 대신 printf라는 함수가 있음. 글자나 단어, 문장을 적을 때는 언제나 텍스트에 " " 쌍따옴표로 감싸야 함.

그리고 우리가 일상에서 문장의 끝에 마침표(.)를 붙이는 것처럼 C에선 세미콜론(;) 을 붙여야 함. (\n은 줄바꾼의 기능으로 키보드의 ENTER의 기능과 동일함)

#include <stidoc.h> 는 "stdio.h"라는 이름의 파일을 찾아서 "printf" 함수에 접근할 수 있도록 해줌. 이것은 지금 크게 중요하지 않고 지금 중요한 것은 printf("hello, world")

우리가 Word로 문서를 저장했을 때 "문서.docx"와 같이 .docx가 붙는 것처럼
C로 작성한 코드는 "파일이름.c" 로 저장해야 함. (확장자 ".c"는 C로 작성된 코드라는 의미)

컴파일러

우리가 직접 작성한 코드는 "소스 코드" 라고 불림. 이를 2진수로 작성된 "머신 코드"로 변환해야 컴퓨터가 이해할 수 있음. 이런 작업을 컴파일러라는 프로그램이 수행해줌

터미널창의 명령어 프롬포트에서 $ 기호 옆에 우리가 원하는 명령어를 입력하면 되고, clang hello.c라는 명령어는 "clang" 이라는 컴파일러로 "hello.c"라는 코드를 컴파일하라는 의미

그 결과 a.out 이라는 파일이 생성됨. 터미널이 ./a.out 명령어를 실행하면 컴퓨터가 현재 디렉토리에 있는 a.out이라는 프로그램을 실행시켜줌 (.은 지금 있는 현재 폴더를 나타냄)

clang

관련 문서를 읽어보면, 출력과 관련된 인자로 -o를 사용할 수 있음. 그리고 어떤 이름이든 지정하여 머신코드 파일을 저장할 수 있음. 그럼 이제 터미널에 ./a.out 대신 ./hello라고 입력할 수 있고 결과는 같음

명령어

ls

명령어 프롬포트를 사용하면 마우스로 하는 모든 일을 할 수 있음. 이 프로그래밍 환경에서도 list를 의미하는 명령어인 ls를 입력할 수 있음. 이는 과거에 정한 약어로 그렇게 탄생한 ls 명령어는 현재 폴더나 디렉토리에 있는 파일의 리스트를 보여줌.

a.out과 hello 뒤에 있는 *는 실행 가능하다는 뜻으로, 즉 컴퓨터가 이해할 수 있는 머신코드라는 말. 반면 hello.c는 없으니 소스코드라는 뜻! 이런 식으로 머신코드와 소스코드를 구분할 수 있음

rm

삭제를 의미하는 rm 뒤에 a.out을 입력하고 엔터를 누르면 파일을 지울 거냐고 물어봄. 프롬포트를 보면 물음표 뒤에 커서가 깜빡이는데, '예'라는 의미로 y나 yes를 입력할 수 있음

ls, rm과 같은 입력 가능한 다른 명령어들도 있음. 폴더를 만드는 mkdir이나 폴더를 지우는 rmdir 명령어도 있음. 물론 이걸 모두 외울 필요는 없지만 한 가지 기억해야 할 것은 마우스와 그래픽 UI로 할 수 있는 모든 일을 명령어만으로도 할 수 있다는 것!

2) 문자열

지난번에 스크래치로 사용자로부터 이름을 입력받아 hello란 단어와 연결한 결과를 말함. 이를 C에선 어떻게 할까? 이는 결국 특정한 규칙과 패턴을 따르고 시간이 지나면 익숙해짐.

get_string

스크래치의 ask 함수와 가장 비슷한 건 get_string이라는 C 함수. string은 프로그래머들이 단어나 구절, 문장을 부르는 말

문자열을 입력할 때는 단어든 구절이든 알파벳 문자든 반드시 양 끝을 쌍따옴표로 감싸야 함. 더 보기 좋게 표시하기 위해 \n을 써서 줄바꿈을 했지만 필수는 아님

변수

get_string 함수를 이용해 사용자에게 이름을 물어보고 입력받았다면 그 답변을 활용하기 위해 값을 저장할 변수를 지정할 수 있음.

answer = get_string("What's your name?\n")

데이터 타입

C는 오래된 언어이기 때문에 변수가 저장하는 데이터의 종류를 아주 정확하게 명시해줘야 함. 따라서 변수명의 왼쪽에 저장하고자 하는 값의 종류가 문자열임을 알려주기. 숫자를 비롯한 다양한 종류의 값들도 있지만 지금은 문자열을 저장하는 것이기 때문에 string & 세미콜론으로 마무리

string answer = get_string("What's your name?\n");

수학에서 x=y는 x와 y가 같다는 뜻이지만 프로그래밍 언어에서 =의 의미는 오른쪽에서 왼쪽으로 가는 화살표와 비슷함. 이 =는 엄밀히 말하면 같다는 뜻이 아니라 지정한다는 뜻임. 할당 연산자라고도 함. 오른쪽에 있는 내용을 왼쪽으로 옮긴다는 것
=> 컴퓨터의 메모리 어딘가에 사용자의 이름이 저장되어 있는 것

C엔 join 함수가 없음. printf는 뭔가를 화면 상에 출력하고 싶을 때 사용하는 함수로 이걸 사용. 그리고 괄호를 쓸 건데 괄호 사이에는 프로그래밍에서 인자(argument) 혹은 매개 변수(parameter)라고 하는 우리의 입력이 들어감.

$s

우리는 "hello, answer"이 아닌 hello 뒤에 이 프로그램을 사용하는 사람의 이름을 넣으려는 것이므로 합치기 위해 C에선 형식 지정자라는 것을 사용함. 즉 화면 상에 출력하고자 하는 구절이나 문장을 적는데 그 값이 뭔지는 아직 모른다면 %와 문자열을 의미하는 s를 적어 형식 지정자를 사용

string answer = get_string("What's your name?\n");
printf("hello, %s\n", answer);

스크래치와 같이 C의 함수들은 인자를 받지 않거나 하나의 인자를 받거나 여러 개의 인자를 받을 수 있음. 만약 여러 개의 인자를 받는다면 쉼표로 구분해 줘야 함. 즉 printf가 작동하는 방식은 관련 문서를 읽거나 배우면 알 수 있는데, 먼저 쌍따옴표 사이에 들어간 하나의 문자열을 입력으로 받는데 거기 형식 지정자가 있다면 쉼표와 변수명을 같이 입력해 줌으로써 컴퓨터에게 가져와야 할 값을 알려주는 것

그럼 이 둘의 코드는 같음

#include <stdio.h>

int main(void)
{
    string answer = get_string("What's your name?\n");
    printf("hello, %s\n", answer);
}

첫 번째 에러

string.c 파일 작성 후 clang -o string 명령어를 실행하면 에러가 생김. 첫 번째 에러에 집중하기. 나머지는 거기서 나온 허상일 뿐임

문제를 진단해보면 우리가 실행한 명령어는 clang -o string로, 입력은 string.c에 있는 소스코드고 출력은 string이라는 파일 안의 머신코드가 되기를 바라는 것. "에러가 시작된 곳은 string.c의 5번째 줄입니다. 선언되지 않은 식별자 string 사용. stdin을 입력하려 하셨나요?" 라고 나옴.

여기서 컴퓨터가 헷갈린 것으로, 엄밀히 말하면 지금 이 단계에서는 문자열이라는 건 C에 없음. 그건 앞으로 우리가 몇 주간 사용할 일종의 보조 바퀴와도 같음. 컴퓨터가 문자열을 구현할 때 실제론 어떤 방식으로 구현되는지 살펴봄.

문자열은 이 강의가 제공하는 cs50.h라는 파일 안에 있음. 즉 stdio.h라는 파일이 있었던 것처럼 여기서 io는 입출력을 의미함. stdio.h라는 파일에서 printf를 가져왔던 것처럼 get_string과 같이 여기서 사용할 다른 함수들도 모두 cs50.h라는 파일 안에 저장되어 있는 것

#include <cs50.h>
#include <stdio.h>

int main(void)
{
    string answer = get_string("What's your name?\n");
    printf("hello, %s\n", answer);
}

=> 즉 이 코드를 컴파일할 때 나타났던 문제의 원인은 문자열이 뭔지 컴퓨터가 몰랐기 때문임

다시 컴파일하면 여전히 버그가 있음. 보통 빨간색은 나쁜 뜻으로 실제로 이건 에러임

에러 : 이 명령어를 실행했더니 네 main 함수에 문제가 있다. get_string 함수가 정의되지 않았다

CS50 라이브러리

CS50 라이브러리를 사용할 때는 두 가지를 명심해야 함.
먼저 소스코드에서는 컴퓨터에게 cs50.h라는 파일을 추가하라고 해야 함. get_string 함수나 문자열과 같은 개념이 실제로 구현되어있는 파일임. 하지만 코드를 컴파일할 때 중복되는 것 같지만 아까와는 다른 이유로 다시 한 번 컴퓨터에게 cs50에 있는 get_string 함수나 문자열과 같은 것들을 구현하는 모든 코드를 추가하도록 해야 함

아까 같이 적은 후 cs50 파일과 연결하도록 하는 -lcs50라는 특별한 명령어를 추가. -l은 연결을 의미하고 그 뒤는 cs50
=> clang -o string string.c -lcs50
그리고 이게 뜻하는 바는 우리 프로그램의 0과 1들은 바로 이 string.c에서 나옴.

CS50의 작성자도 과거에 get_string 함수나 문자열과 같은 변수를 구현하기 위해 C로 코드를 작성했을 것임. CS50 라이브러리의 0과 1들은 클라우드 어딘가에 저장되어 있음. 그들은 우리의 0과 1들에 연결되어야 함. 즉 명령어로 두 코드가 한 프로그램으로 실행될 수 있도록 연결시키는 것

make 명령어

이건 쓸데없이 복잡하고 어려움 더 좋은 방법은 우리 코드를 컴파일할 때 이런 명령어를 기억하지 않고 개념만 이해하고make string으로 string이라는 프로그램을 만들어달라고만 하면 끝임. 그럼 이 흰색 출력들이 모두 자동으로 만들어짐. 그럼 make라는 명령어는 알아서 어떤 인자를 사용해야 할지 파일명은 무엇으로 할지 등을 찾아줌

따라서 지금부턴 make와 프로그램의 이름만을 입력해 컴파일

질문

Q. make는 일반적인 명령어? 아니면 CS50에만 있는 것?
일반적인 명령어. 유닉스와 리눅스를 사용하는 컴퓨터들에 포함되어 있는 일반적인 툴.

그리고 우리가 사용하는 샌드박스 툴은, 그 자체로 클라우드 상의 컴퓨터임. 물론 입력창과 터미널창 두 개 뿐이지만 CS50 샌드박스에 로그인하면 리눅스라는 운영체제로 돌아가는 클라우드 서버의 접근 권한을 갖는 것이고 clang, make, ls, rm과 같은 명령어들은 모두 그 운영체제 안에 있음

Q. ?
hello.c는 소스코드고, hello는 머신코드!

make는 우리를 도와주는 아주 똑똑한 리눅스라는 운영체제에 있는 프로그램이고 요즘엔 맥과 윈도우에도 포함되어 있음. make hello라고 하면 hello.c라는 파일을 찾음. 찾고 나면 hello라는 파일을 만듦. 아이콘을 더블클릭하는 프로그램은 아님

Q. make는 컴퓨터에 저장된 건가요 아니면 클라우드 기반 컴퓨터에 저장된 건가요?
클라우드에 저장되어 있음. CS50 샌드박스 그리고 곧 나올 CS50 랩이라는 클라우드 기반 환경에 저장되어 있음

이는 리눅스와 맥 컴퓨터 모두에서 작동되도록 설계됐지만, 소프트웨어는 조금씩 다르기 때문에 소프트웨어 개발 분야에서 매우 유명한 운영체제인 리눅스에서 표준화한 것

3) 조건문과 루프

profile
꾸준히 자유롭게 즐겁게

0개의 댓글