C언어 입문 3장부터 6장(3)까지 정리

이성준·2023년 2월 22일
3

C 자료구조

목록 보기
4/12

나는 지금 이지스퍼블리싱에서 발간한 'C언어 입문'책을 3학년 1학기에 듣는 자료구조에 대비하기 위해서 복습하고 있다.
2회독이고 파이썬으로 코딩을 쫌 하다 보니 11장까진 무난해서 쭉 복습을 진행했다 2번 혹은 3번에 나눠서 이를 정리할 예정이고,
내 생각에 그때 그때 찾아봐도 괜찮을 것 같은 내용은 뺐다

어차피 다시 봐야하니깐 미련두지 말자
(내 1전공인 수학과 동기들이 공부할 자료기에 좀 알아듣기 쉽게 자세히 적겠다)

3장(지난번 블로그인 bit와 byte에 이어서)

자료형의 종류

C언어는 만들어진지 오래됐고 어셈블리어(기계어)에 가까운 언어이다. 그 당시에는 하드웨어가 현재처럼 발달하지 않았고, 따라서 개발자가 메모리를 어떻게 하면 효율적으로 쓸 수 있을지에 대해서 고민했다고 들었다.
그래서 그런지 C언어는 이런 자료형을 여러가지로 만들어 놨는데, 구분하자면 크게 3가지로 나눌 수 있겠다.

  • Char - 보통 알파벳은 1byte를 차지한다 이때 Char은 1byte의 크기를 갖고 있다.(한글은 2byte의 크기를 갖는다)
    (부호에 관해서는Signed와 Unsigned가 있는데 Signed가 일반적인 경우 Unsigned가 특별한 경우이다
    내가 위에서 알파벳과 한글이야기를 했다고 Char을 문자를 저장하는 공간이라고 생각하면 오산이다 그저 메모리로 받아들여야 한다.)
  • Int - Integer 자료형은 기본이 4byte라고 생각하면 된다 하지만 short를 붙여주면 2byte크기로 바뀐다
    ( 여기서 하나 알고 가야 할 것은 long과 short 가 있는데 long이 기본이고 short가 특수한 경우/
    부호에 관해서는Signed(부호가 있음)와 Unsigned(부호가 없음)가 있는데 Signed가 일반적인 경우 Unsigned가 특별한 경우이다)
    한번 생각을 해보자 예를 들어, 4바이트의 Unsigned Int자료형의 Number라는 변수를 초기화 했다고 생각해보자. 다음과 같을 것이다.
    unsigned int Number = 3 //이때 long은 기본값(default 값)이기 때문에 생략이 가능하다
    위 와 같이 변수를 선언한다고 하면 우리는 지금 4바이트 변수 Number라는 박스안에 3을 담은 것이다 이때 4바이트는 32비트 이므로 총 0부터 2322^{32} 개의 숫자를 표현할 수 있다. 왜냐? unsigned이니깐 부호가 없기 때문이다
    short int Number = 3 //이때 signed는 기본값(default 값)이기 때문에 생략이 가능하다
    위의 경우는 2바이트 변수 Number라는 박스안에 3을 담은 것이다 이때 2바이트는 16비트 이므로 총 2162^{16}개의 숫자를 표현할 수 있는데 이때 0부터 2152^{15}개의 양수와 2152^{15}개의 음수를 표현할 수 있는 것이다. 왜냐? signed 이니깐 부호가 있기 때문이다 따라서 양수 215+215=2162^{15} + 2^{15} = 2^{16}이다. 비트 16개중에 부호로 쓸 비트 1개가 빠지니깐 그렇다고 생각하면 된다
    → 이외의 경우도 생각해 볼 수 있을 것이다 한번 생각해 보길 바란다
  • Float - Float는 좀 복잡하다 하지만 매우 중요하니 잘 알아두고 넘어가야 한다. Float는 일단 signed unsigned가 존재하지 않는다 무조건 signed이니 부호는 생각하지 말자 Float에는 두가지가 있는데 하나는 4Byte Float 형과 다른 하나는 8Byte double형이 있다. 여기서 부동소수점 개념을 얘기를 잠깐 하자면 우리는 평소에 356.3 과 같은 숫자를 있는그대로 356.3 으로 표현하곤 했다. 하지만 코딩을 하다보면 3.5631e+2로 쓰기도 한다. 눈치 챘겠지만 뒤에 1e가 10을 의미하는 것이고 +2가 제곱을 의미하는 것이다. 하나 더 예시를 들자면 0.047은 어떻게 쓸 수 있나 4.71e-2로 쓸 수 있는 것이다.
    다시 돌아와서 Float에는 4byte Float와 8byte Double이 있는데 기억해야 될 점은 4byte는 소수점아래 6자리 까지만 숫자를 기억할 수 있고 Double은 소수점 아래 14자리까지 기억할 수 있다는 것이다. 자세한 비트 단위의 설명은 책을 참고하길 바란다 !

4장(상수와 변수)

→ 4장은 위에서 변수를 초기화하는 방법과 10진수 8진수 16진수에 관해서 설명하고 있는데 나중에 필요하다면 책을 참고해 보길 바란다. 현재 빠르게 복습하는 과정에선 불필요하다고 느껴진다

5장(함수)+6장4절까지

함수의 구조와 함수원형

책에 비해서는 매우 간단하게 설명을 진행하겠다.
먼저, 함수의 필요성에 대해서 말을 시작해보자. 함수는 왜 필요할까?
우리가 덧셈을 한다고 해보자 만약 덧셈을 할때마다 4+5 이렇게 해도 괜찮다. 하지만 더 복잡한 행위를 정의해놓는다면 그것을 사용할때마다 일일히 치지않고 편하지 않을까? 당연하다 이는 물론이거니와 유지보수도 훨씬 편할 것이다. 그래서 함수를 사용하는 것이고 C언어로 작성된 코드는 이런 함수들의 집합체라고 할 수 있다.
함수를 정의 하는 방법에 대해서 소개하겠다 함수는 다음과 같은 방법으로 정의한다

(return시 반환될 반환형) 함수이름(함수에 넣을 인자){

}

Ex>
Void main(int Number1, Float Number2, Char Number3){

}

위에서 Ex>로 보여준 main함수는 C언어에서 있는 고유의 함수이다 모든 C언어 프로그램은 main이라는 함수를 시작함수로 정해놓고 이어 나간다. 또 하나 C언어를 작성할때 규칙이 있는데 main 시작 함수 이외에 함수를 정의할때는 main함수 위에 정의를 해놓아야 한다는 것이다.
예를 들어, 덧셈함수를 정의해보자.

#include <stdio.h>

int sum (int value1, int value2){
    int value = value1 + value2;
    return value;
}

void main(void){
    int result = sum(3,5); 
    printf("this is result %d",result);
    // return 0; 보이드 형식으로 정의한 함수 뒤에 return을 넣으면 오류로 처리된다
    // 하지만 return뒤에 아무것도 적지 않고 return;이면 오류가 발생하지 않고 함수를 끝내기만한다
}

위의 함수를 이해한다면 오늘 완벽히 이해한 것이다 하나씩 뜯어보겠다
먼저 위에 헤더파일 <stdio.h>를 include를 했다 이는 C언어 표준 라이브러리 함수이다.
뭔가 굉장히 많은 모르는 말이 지나갔는데 그냥 읽고 넘겼을 것이다 여기서 잠깐 6장 내용으로 넘어가겠다

  • 실행파일이 만들어지는과정
    → 실행파일(.exe)가 어떻게 만들어지는지 설명해보겠다.
    기본적으로 다음과 같고 앞에 두단계를 거친 여러 목적파일을 연결해 하나의 실행파일을 만드는 것이다.
    [컴파일전 .c 파일] → [컴파일후 기계어로 된 .obj 목적파일] → [이러한 목적파일이 합쳐진 실행파일.exe]
    위와 같다. 그렇다면 실행파일을 만들때 어떤식으로 만들면 시간이 덜 걸릴까 당연하게도 컴파일하는 과정을 뺀 목적파일이 많이 구성돼 있으면 구성돼 있을수록 실행파일이 더 빨리 만들어질 것이다. 그러기 위해서는 목적파일로 미리 몇몇 파일은 만들어놓고 실행파일을 만들때 연결을 지어야지 빠를텐데 따라서 몇몇 유지보수할 필요가 없는 자주사용하는 함수들은 목적파일로 바꿔놓으면 좋을 것이다. 그런데 이 처음부터 목적파일이었던 파일과 컴파일후 목적파일로 된 파일을 연결짓는 과정에서, 처음부터 목적파일로 만들어놓은 파일중 일부 함수는 사용하지 않는데도 연결지어버렸기 때문에 실행파일에 사용하지 않는 함수들도 포함돼있다
    이를 해결한게 라이브러리 파일이다 이 목적파일을 library 파일(.lib) 로 변환시켜두면 필요한 함수만 라이브러리 파일에서 뽑아서 쓰면 되는 것이다.
    Tip> 특히 Python에서는 무수히 많은 라이브러리 파일이 있고 여기서 확실하게 알아두고 가는 것을 추천한다

  • 헤더 파일이란 무엇일까?
    위에서 #include <stdio.h>를 보았을 것이다 이게 무엇인지 궁금할테다.
    우리는 위에서 라이브러리 파일을 보았다. 우리가 이 라이브러리 파일과 object 파일에 Add()함수 Sub() 함수를 정의해놨다고 해보자 따라서 우리는 우리가 지금 작성중인 코드에 Add(1,3)을 추가했다고 해보자 과연 잘 돌아갈까?
    정답은 아니다 왜냐하면 우리가 지금 작성하고 있는 파일에서는 Add함수가 어떻게 생겨먹었는지 모르기 때문이다.
    따라서 우리는 Add라는 함수는int Add(int n1, int n2) 라고 우리가 작성하고 있는 코드에 선언을 해줘야 한다. 하지만 라이브러리 파일에 있는 함수를 사용할때마다 선언을 해주어야 하는 것에 불편함을 느꼈고 따라서 이런 함수 원형을 모아두고 선언해서 사용하는데 이를 헤더파일(*.h)라고 한다 한마디로 라이브러리 설명서라고 생각하면된다. 따라서 우리는 라이브러리에 있는 함수를 사용하기전에 이런 헤더파일을 먼저 읽게 하는 것이다.
    헤더파일을 읽게하는 방법은 전처리(preprocessing)를 하는 방법인 #을 사용해서 하는 것이고 다음과 같이 한다
    #include <stdio.h> stdio.h라는 헤더파일을 포함한다는 것이고 stdio.h는 vscode,visual studio에서 경로를 알고 있기 때문에 꺽쇠를 사용해서 포함하고
    만약 우리가 직접 헤더파일을 만드는 경우 다음과 같이 큰 따옴표"" 를 사용한다
    #include "C:\users\Cworking\my.h"
    우리는 전처리를 하면서 #을 사용한다고 했다. 이렇게 전처리를 하는 것에는 다음과 같이 상수를 치환하는 것도 있고 간단한 함수를 치환할 수도 있다

#define MAXCOUNT 3 ← 우리는 이 소스파일에 있는 MAX_COUNT라는 이름을 모두 3으로 치환할거야

#define PowValue(a) a*a ← 우리는 이 소스 파일에 있는 PowValue(a)라는 이름을 모두 a*a로 치환할거야

#include <stdio.h>

int sum (int value1, int value2){
    int value = value1 + value2;
    return value;
}

void main(void){
    int result = sum(3,5); 
    printf("this is result %d",result);
    // return 0; 보이드 형식으로 정의한 함수 뒤에 return을 넣으면 오류로 처리된다
    // 하지만 return뒤에 아무것도 적지 않고 return;이면 오류가 발생하지 않고 함수를 끝내기만한다
}

이제 다시 위로 돌아오자 이제 많은 것들이 보일 것이다 위에서 말했듯이 시작함수인 main함수부터 시작을 할 것이다 여기서
main앞에 있는 void는 반환 자료형이고 우리가 현재 반환하는것이 없다는 것이다 또 main(void)에서 void는 인자로 받는것이 없다는 뜻이다.
result라는 변수를 초기화 하면서 위에서 정의해둔 sum 함수를 호출 했는데 sum함수에서 게산을 쭉 한 이후에 계산한 값인 value를 return해주면서 result 변수를 value값으로 초기화 했다.
그 이후 printf라는 함수를 호출했는데 여기서 printf는 stdio.h라는 헤더파일에 미리 함수 원형이 저장돼있다 또 printf는 C언어 컴파일러를 만든 회사가 만들어놓은 C표준 라이브러리에 저장돼있다.

다음시간에는 배열과 포인터 전까지 블로그를 작성해보겠다

profile
Time-Series

2개의 댓글

comment-user-thumbnail
2023년 2월 24일

출석 check

함수의 구조와 함수원형 부분을 읽고 잘 몰랐던 내용을 확실하게 이해할 수 있었습니다!!

답글 달기
comment-user-thumbnail
2023년 2월 24일

종욱 하이ㅋㅋ

답글 달기