# 3. 배열

### 1) 컴파일링

make 나 clang을 사용해 프로그램을 실행할 때 네 개의 단계를 거친다.

* 전처리
* 컴파일링
* 어셈블링
* 링킹

각 단계가 무엇인지, 단계별로 어떤 작업을 수행하는지 알아보자.

**전처리(Precompile)**

전처리기에 의해 수행되며, # 으로 시작하는 C 소스 코드는 실질적인 컴파일이 이루어지기 전 무언가를 실행하라고 알려준다.

**컴파일(Compile)**

전처리기가 전처리한 소스 코드를 생성하고 나면 그 다음 단계는 컴파일이다. 컴파일러라는 프로그램은 C 코드를 어셈블리어라는 저수준 프로그래밍 언어로 컴파일한다. 컴퓨터가 이해할 수 있는 언어와 최대한 가깝게 프로그램을 변경하는 것이다.

\*컴파일이라는 용어는 소스 코드 > 오브젝트 코드로 변환하는 전 과정을 통틀어 일컫기도 하지만, 구체적으로 전처리한 소스 코드를 어셈블리 코드로 변환하는 단계를 말하기도 한다.

**어셈블(Assemble)**

소스 코드가 어셈블리 코드로 변환되면, 어셈블리 코드를 오브젝트 코드로 변환하는 과정을 거친다. 컴퓨터의 중앙처리장치(CPU)가 이해할 수 있는 0과 1의 형태로 변경하는 과정이다. 이 작업은 어셈블러라는 프로그램이 수행하며, 컴파일할 파일이 하나라면 여기서 작업이 끝나지만 그렇지 않다면 링크라 불리는 단계가 추가된다.

**링크(Link)**

프로그램이 여러 파일로 이루어져 하나의 오브젝트 파일로 합쳐야 할 때 진행하는 단계이다. 링커는 여러 오브젝트 코드 파일을 실행 가능한 하나의 오브젝트 코드 파일로 합쳐준다.

이 네 단계를 거치면 실행 가능한 파일이 완성된다.

### 2) 디버깅

**버그 = 코드에 들어있는 오류**

<figure><img src="https://534473029-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fh5bANRFbqQiBiOjIxpbm%2Fuploads%2FdLdu7DPGNS6qsGZa7a5a%2Fimage.png?alt=media&#x26;token=4df40f19-8509-4816-ba36-031b660f5e43" alt=""><figcaption><p>인류 최초의 버그</p></figcaption></figure>

**디버깅 = 코드에 있는 버그를 식별하고 고치는 과정**

디버깅의 기본은 실행되는 코드의 특정 행에서 멈춰서 확인하는 것으로 디버거를 사용해 프로그래머는 멈춰진 지점에서 무슨 일이 일어나는지 볼 수 있다. 프로그램이 멈추는 지점을 중지점이라하고, 프로그래머는 프로그램이 내리는 모든 결정을 단계별로 따라갈 수 있게 한다.

printf 를 사용해 확인하는 방법도 있고, IDE에서 브레이크포인트를 설정해 확인하는 방법도 있다.

### 3) 코드의 디자인

다른 사람들과 프로젝트를 진행하면 코드는 나 혼자의 것이 아니다. 내 코드가 프로그램에 문제 없도록 만들어야 하고, 프로젝트에 참여하는 모든 사람들이 이해하고, 사용할 수 있도록 주의를 기울여야 한다.

내 코드를 다른 사람에게 설명할 수 있어야 한다. 부담스럽다면 작은 인형을 앉혀놓고 설명해보자

### 4) 배열(1)

**메모리**

C에는 여러 자료형이 있고 각 자료형은 서로 다른 크기의 메모리를 차지한다.

* bool 불리언 1바이트
* char 문자 1바이트
* int 정수 4바이트
* float 실수 4바이트
* long 정수 8바이트
* double 실수 8바이트
* string 문자열 ?바이트

<figure><img src="https://534473029-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fh5bANRFbqQiBiOjIxpbm%2Fuploads%2FWKYIblJ612qVy4LUEdgK%2Fimage.png?alt=media&#x26;token=062de003-0e12-4917-ab41-230ffd64b7f7" alt=""><figcaption><p>RAM(Random Access Memory) 자유롭게 내용을 읽고 쓰고 지울 수 있는 기억장치</p></figcaption></figure>

RAM이 메모리 역할을 한다. 여러 개의 노란 사각형이 메모리를 의미하고, 각 사각형이 1바이트를 의미한다고 생각하기

**배열 Array**

배열은 같은 자료형의 데이터를 메모리상에 연이어 저장하고 이를 하나의 변수로 관리하기 위해 사용된다. 이때, 배열에 포함된 데이터는 순서를 가진다.

### 5) 배열(2)

**전역변수**

코드 전반에 거쳐 바뀌지 않는 값, 관례적으로 대문자로 표기한다.

**배열의 동적 선언 및 저장**

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

float average(int length, int array[]);

int main(void)
{
    // 사용자로부터 점수의 갯수 입력
    int n = get_int("Scores:  ");

    // 점수 배열 선언 및 사용자로부터 값 입력
    int scores[n];
    for (int i = 0; i < n; i++)
    {
        scores[i] = get_int("Score %i: ", i + 1);
    }

    // 평균 출력
    printf("Average: %.1f\\n", average(n, scores));
}

//평균을 계산하는 함수
float average(int length, int array[])
{
    int sum = 0;
    for (int i = 0; i < length; i++)
    {
        sum += array[i];
    }
    return (float) sum / (float) length;
}
```

배열의 크기와 각 인덱스 값을 유저가 입력하면서 다양한 상황에서 사용할 수 있게 된다.

### 6) 문자열과 배열

문자열(string) 자료형 데이터는 문자(char) 자료형 데이터의 배열이다.

string s = “HI!” 에서 s 는 문자의 배열이기에 메모리상에 다음과 같이 저장되고, 인덱스로 접근할 수 있다.

<figure><img src="https://534473029-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fh5bANRFbqQiBiOjIxpbm%2Fuploads%2FPzv2Oh0pwzQCPqrjuRT0%2Fimage.png?alt=media&#x26;token=2209a6c8-2826-44a8-8e58-b672719a4c6b" alt=""><figcaption></figcaption></figure>

여러 문자열이 동시에 선언된 경우, 다음과 같이 저장된다.

<figure><img src="https://534473029-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fh5bANRFbqQiBiOjIxpbm%2Fuploads%2FnXw2DvOKUxX333tAV9Bf%2Fimage.png?alt=media&#x26;token=d55dd0fa-d04d-4d4a-bbd7-56f19b74a8f5" alt=""><figcaption></figcaption></figure>

그래서 name\[i]\[j] 와 같은 표현을 사용할 수 있다.

### 7) 문자열의 활용

이러한 특징을 가진 문자열은 각 요소와 길이를 이용해 다양한 방법에 사용할 수 있다.

반복문을 활용해 한 글자씩 출력하거나 특정 문자와 비교하거나 대문자, 소문자 변환을 하거나 등등

이러한 방법들은 직접 구현할 수도 있지만, 라이브러리의 다양한 함수를 통해서도 적용할 수 있다.

### 8) 명령행 인자

main 함수에 void 가 아닌 argc, argv를 입력한다면

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

int main(int argc, string argv[])
{
    if (argc == 2)
    {
        printf("hello, %s\\n", argv[1]);
    }
    else
    {
        printf("hello, world\\n");
    }
}
```

첫번째 변수 argc는 main 함수가 받을 입력의 개수이다. argv\[]는 입력이 포함된 배열이다.

프로그램을 실행할 때 명령행에서 입력 받은 값은 문자열이다. 따라서 argv\[]는 string 배열이 된다.

argv\[0]는 프로그램의 이름으로 저장되고, 하나의 입력이 더해질 때마다 argv\[i]에 저장된다.
