프로그래밍 #1

Updated:

이 포스팅은 온전히 직접 공부한 것을 기반으로 기록한 페이지 입니다.

Ch 1. 프로그래밍

프로그래밍은 흔히 말해 코드를 작성하는 “코딩”이라고 하는 것처럼 컴퓨터와 소통하기 위해 작성하는 것입니다.

프로그램을 만들 때 Data Structure나 Algorithm을 잘 이용한다면 같은 동작을 하는 코드라도 코드 길이나, 메모리 사용량 등이 천차만별합니다.

간결하고, 효율적인 코드를 짜면 프로그래머끼리 알아보기 더 쉽거나, 기술적인 코드로 인해 새로운 것을 알게 된다거나, 더 좋은 시스템을 만들 수 있겠죠.

그래서

프로그램을 작성할 땐 작고, 효율적이고, 깔끔하게

Ch 1.1 프로그래밍 이란?

한국사람에겐 한국어를

안녕하세요. 저는 이명로 입니다.
올해는 2021년입니다.

컴퓨터에게는 기계어(프로그래밍 언어)를

int a=0, i=0;

while(i < 10)
{
	i++;
	printf("%d", i);
}

컴퓨터는 기계어만 이해할 뿐 우리말을 이해하지 못합니다.

하지만, 기계어는 난해하며 다루기 어렵습니다.

기계어는 비트(bit)와 바이트(byte)로 구성돼 있으며, 기계 아키텍처별로 다릅니다.

또 기계어는 각 명령의 인자 값, 명령의 상호작용, 기타 여러 사항을 알아야 합니다.

이런 방식의 프로그래밍은 매우 힘든 작업이며 직관적이지도 않습니다.

이처럼 복잡한 기계어 프로그래밍을 하려면 변환기가 필요한데, 어셈블러 라는 기계어 변환기가 필요합니다.

어셈블리어는 명령과 변수를 숫자가 아닌 이름으로 나타낼 수 있으므로 기계어 보다는 이해가 쉽지만

어셈블리어도 어렵고 명령 이름이 상당히 난해하며, 기계 아키텍처 별로 다르기 때문에

이러한 문제를 해결하려고 나온 것이 컴파일러입니다.

컴파일러는 기계어, 어셈블리어와 같은 로우레벨 언어 보다 쉬운 하이레벨 언어를 기계어로 변환하는 변환기입니다.

하이레벨 언어를 작성하고 컴파일러를 이용해 기계어로 변환 시킬때는

하이레벨 언어의 명령 체계 규칙(문법)을 엄격하게 따라야 합니다.

그렇지 않는다면 컴파일러가 언어를 이해하지 못해 기계어로 변환할 수 없게 됩니다.

설명한 언어들의 간단한 예시

  • 기계어
[  op  |        target address        ]
    2                 1024               decimal
 000010 00000 00000 00000 10000 000000   binary
  • 어셈블리어
.model small
.stack 100h

.data
hello_message db 'Hello, World!',0dh,0ah,'$'

.code
main proc
      mov    ax, @data
      mov    ds, ax

      mov    ah, 9
      mov    dx, offset hello_message
      int    21h

      mov    ax, 4C00h
      int    21h
main endp
end main
  • 하이레벨 언어(C 언어)
int a=0, i=0;

while(i < 10)
{
	i++;
	printf("%d", i);
}

이 중 위의 프로그래밍 언어를 설명할 때와 똑같은 코드가 있는데,

기계어라고 써놨지만 사실은 하이레벨 언어 중 C언어 였다.

요약 -
  • 기계어: 컴퓨터가 알아들을 수 있는 언어

  • 어셈블리어: 기계어보다 쉬워서 사람이 이해하기 쉬운 언어

  • C언어(하이레벨 언어): 사람이 이해하기 쉬운 언어이고, 컴파일러라는 친구가 기계어로 바꿔준다.

Ch 1.2 가상 코드

가상 코드(Pseudo-Code): 프로그래머가 사용할 수 있는 또 다른 형태의 프로그래밍 언어

가상 코드는 하이레벨 언어와 유사한 구조지만 코드 대신 영어를 씁니다.

여러 프로그래머들이 주로 사용하는 언어가 다를때 가상 코드를 이용해 명령 구조를 쉽게 표현할 수 있습니다.

가상 코드는 사람이 보기 위함이라 형식이 엄격하게 정해져 있지는 않기 때문에 여러 사람들이 가상 코드를 작성할 때 약간씩 다른 방법으로 작성할 때도 있습니다.

가상 코드는 영어와 하이레벨 언어를 이어주는 언어라고 할 수 있고, 보편적인 프로그래밍 개념을 표현하는 언어입니다.

Ch 1.3 제어 구조

제어 구조는 프로그램에 빠질 수 없는 구조인데. 코딩을 해서 프로그램을 만들면

프로그래머가 원하는 의도대로 프로그램이 흘러가게 하도록 하는게 제어 구조입니다.

[조건문]

그 중 조건문에 대해 설명을 먼저 하겠습니다.

예를 들어 숫자 1이 숫자 5보다 작은지 큰지를 비교한다 할때 우리는 당연히 숫자 5가 크다는 것을 알고 있죠.

그러나 컴퓨터는 그렇지 못하기에 아래 코드처럼 표현해야 합니다.

  • 조건문 예시

if(1 > 5) // 1이 5보다 큽니까?
{
    // True(진실) 일때
	printf("1이 5보다 큽니다.");
}
else if(1 > 3) // if가 거짓일때 실행, 1이 3보다 큽니까?
{
    // True(진실) 일때
	printf("1이 3보다 큽니다.")   
}
else // else if가 거짓일때 실행
{
    // if도 else if도 실행되지 않으면, else 실행
	printf("1이 5보다 작습니다.");
}

if, else-if, else 처럼 조건문은 True(진실) 이어야 블록({ }) 내 명령이 실행이 되고 False(거짓) 이라면 다음 조건으로 넘어갑니다. ** **만약 다음 조건이 없다면 그냥 넘어가게 됩니다.

대략 조건문은 조건에 충족하면 해당 명령 실행, 아니면 다른 조건 실행 또는 pass 와 같은 작업을 합니다.

위 코드에선 조건문 중 if문을 사용했지만 switch-case문 등의 조건문이 있습니다.

[반복문]

다음은 반복문에 대해 설명을 하겠습니다.

반복문은 지정한 횟수만큼 작업을 반복하는 것인데,

예를들어 1부터 +1 씩 반복해서 10이 되게 만드는 프로그램을 작성한다고 할 때는 아래 코드처럼 표현해야 합니다.

  • 반복문 예시

int num = 1;

while(num < 10) // num이 10보다 작습니까?
{
    // True면 실행
	printf("%d", num); // num 값을 출력 1 ~ 9까지 출력
	num++; // num 값을 1 증가 시킴 
}

printf("%d", num); // num 값 10을 출력

위 코드의 흐름을 설명하면

  1. num에는 값 1이 저장됨
  2. num을 출력하고 값을 증가시킴(10 보다 작을때까지 반복)
  3. 마지막으로 num 값을 출력(num에는 10이 저장되있음)

이런 흐름이고 1 ~ 9까지 증가하다가 num이 9일때 반복문을 마지막으로 수행하고 최종적으로는 10이 출력되는 코드입니다.

위 코드에선 반복문 중 while문을 이용했지만 그 외 for문, do-while문, 또는 언어에 따라 for-each문 등 여러 반복문이 있습니다.

요약 -
  • 조건문: 조건에 따라 참이면 명령 수행, 거짓이면 다음 조건 수행 및 pass

  • 반복문: 지정한 횟수(조건)이 충족될 때 까지 반복해서 명령 수행

Ch 1.4 변수

변수 - 바뀔 수 있는 데이터를 갖고 있는 객체.

상수 - 바뀌는 않는 변수.

사실 반복문 예시 중 코드 내에 int num = 1; 이라는 것은

데이터 형이 int이고 변수의 이름이 num변수에 값 1을 저장한다. 라는 의미입니다.

num에는 처음에 1이 저장되었지만, 반복을 거치며 최종적으로 num에 저장된 값은 10 입니다.

이로써 num이 변수임을 알 수 있습니다. 그리고 C언어에서 변수를 사용할때는 선언을 해야합니다.

[변수 선언]

int main(void)
{
	char a; 	// 문자형 변수 a
	int b;  	// 정수형 변수 b
	int c = 1; 	// 정수값 1이 저장된 정수형 변수 c 
}

Ch 1.2 와 Ch 1.3의 코드 예시들은 C언어라는 하이레벨 언어로 코딩한 것 입니다.

변수가 저장할 수 있는 값의 기준은 데이터 형으로 정해지는데

C언어의 데이터 형은 크게 아래 표로 볼 수 있습니다.

  • 데이터 형 (C 언어)

문자 정수 실수
char short float
  int double

문자 - 문자 1개를 저장 (e.g. ‘a’ )

정수 - 정수를 저장 (e.g. 132)

실수 - 소수를 저장 (e.g. 3.141592…)

그런데 보통 문자를 저장할 때는 한 문자가 아닌 여러 문자로 저장할 텐데,

문자형 변수 1개에 문자가 1개 밖에 저장이 안되면 apple이란 문자를 저장할 땐

문자형 변수 5개를 선언한 후 저장해야 하냐고 생각할 수 도 있는데

물론 그렇게 해도 가능하지만 그러면 코딩할 때 매우 피곤하기 때문에

우리는 배열 이라는 것을 이용합니다.

Ch 1.5 배열

배열 - 데이터 형이 같은 변수들의 집합, 대괄호로 표현함 => [ ]

배열의 핵심은 ?

1. 데이터형이 같다.
2. 변수들의 집합이다.
3. 배열의 시작순서는 0부터다
  • 배열 예시

1: char red[] = "apple";
2: int num[] = [14, 15 ,16];

위 코드는 배열을 사용하는 예시를 보여주는 예시입니다.

1번 줄: apple 이라는 문자열을 red라는 char형 배열에 저장하는 것

2번 줄: 정수 14, 15, 16을 num이라는 int형 배열에 저장하는 것

  • 코드 해석

char red[] int num []
apple 14, 15, 16
방 0번 ~ 4번: [a] [p] [p] [l] [e] 방 0번 ~ 2번: [14] [15] [16]

우선, 코드 해석을 보기 전에 배열에는 크기가 있는데 배열의 원소의 개수가 5개면, 배열의 크기는 5가 됩니다.

  • char red[]

코드 해석의 red라는 char형 배열을 보면 apple이라는 값이 저장되기 때문에 red배열의 크기는 5이고, 각 원소는 0번 ~ 4번 방에 있습니다.

0번방엔 a, 1번방과 2번방은 p, 3번방에는 l, 4번방은 e 라는 의미입니다.

  • int num[]

이번엔 num이라는 int형 배열을 보면 값 14, 15, 16이 저장되고 변수num의 0번방은 14, 1번방은 15, 2번방은 16이 있다는 의미입니다.

사실 배열은 해당 크기만큼 메모리공간을 할당 받는 것인데

위 표의 red라는 배열을 예시를 들면 char형은 1byte이고, red는 char형이 5개가 모여서(5bytes) 배열이 된 것입니다.

  • 메모리 구조
# char red[] = "apple"
 
      [a][p][p][l][e]
100번지              104번지

메모리 구조를 보게되면, 100번지는 red라는 변수의 시작 지점이자 red배열의 0번방이고, 104번지는 red배열의 4번방이 되는 것입니다.

(실제 100번지 104번지에 들어가는 것은 아니고, 비유를 위해서 표현한 것입니다.)

배열은 포인터라는 주소를 참조하는 것과 유사한 관계가 있지만, 코딩의 입문하시는 분들이 보통 선택하는 언어인 Java나 python과 같은 언어는 배열(List)까지만 알면 충분히 쉽게 배우실거 같기에 포인터 부분은 생략하겠습니다.

요약 -
  1. 배열은 데이터형이 같은 변수들의 집합
  2. 배열의 이름은 시작주소(0번방)
  3. 배열과 포인터의 상관관계

마무리하며

공부했던 C언어를 바탕으로 프로그래밍이 무엇인지, 프로그래밍의 기본적인 요소들을 정리해보았는데, 블로그를 해보는 것도 처음이고, 이론적인 부분을 정리하다보니 기억도 새록새록하면서 좋은 시간이었다. 내 나름대로 내용을 최대한 이해하기 쉽고 함축적으로 설명했지만, 아직 많이 부족한 것 같다. 혹시 이 글을 보시고 질문이 있으시거나 궁금한 점, 내용을 토대로 더 알고싶은점이 있으신 분은 이메일이나 DM 주시면 감사하겠습니다.

Leave a comment