C 언어 시작
Updated:
C 언어 시작
C 언어 공부를 시작하기로 했다. TCL에 C 언어 개념들이 잘 정리 되어 있어 참고하여 정리하였다.
이 글은 Chapter 1. C 언어 시작을 정리한 내용이다.
참고한 사이트 : TCLSchool
C 언어 개요
C 언어는 범용성이 있는 언어이며, 현재 주요 운영체제의 커널은 대부분 C 언어를 이용해 구현되어있다.
C 언어는 시스템 프로그래밍으로 주로 사용되지만, 응용 프로그래밍에도 많이 사용되는 프로그래밍 언어이다.
▲커널, 위키피디아
커널은 운영 체제의 핵심 부분으로, 주요 역할은 보안, 자원 관리, 추상화이다.
C 언어 기초
-
정의
C 언어는 프로그래밍 언어이다.
여기서 프로그래밍 언어란 소프트웨어를 작성하기 위한 언어를 의미한다. 프로그래밍 언어는 저급 언어(low-level language)와 고급 언어(high-level language)로 나뉜다. 기계가 이해하기 쉬운 언어와 사람이 이해하기 쉬운 언어를 상대적으로 나눈 개념이다.
기계어는 저급 언어의 대표적인 언어이다. 고급 언어는 사람이 이해하기 쉬운 언어이기 때문에 기계가 이해할 수 있도록 컴파일러, 인터프리터에 의해 번역된다. 저급 언어보다 가독성이 높지만 실행 속도가 느리다.
C 언어는 저급, 고급 언어의 특징을 모두 가진 절차 지향 프로그래밍 언어(procedure-oriented programming language)이다. -
역사
C 언어는 1972년 벨 연구소의 켄 톰프슨(Kenneth Thompson)과 데니스 리치(Dennis Ritchie)가 유닉스(UNIX) 운영 체제에서 사용하기 위해서 개발한 고급 언어이다.
ALGOL 60부터 CPL, BCPL을 거쳐, B 언어를 개발하게 되고, 이후 B 언어를 개선하여 지금의 C 언어를 만들게 된다. -
탄생 배경
C 언어 이전, 유닉스는 어셈블리어라는 저급 언어를 사용하였지만, 하드웨어에 종속적인 언어였기 때문에, 다른 하드웨어로 이식할 수 없었다.
따라서 이식성과 가독성이 필요한 언어가 필요했고 그래서 개발된 언어가 C 언어이다. - 특징
1) 장점- 이식성이 뛰어나다.
- 코드가 복잡하지 않아 상대적으로 유지보수가 쉽다.
- 저급 언어의 특징도 있기 때문에, 하드웨어 제어가 뛰어나다.
- 프로그램의 크기가 작고 실행 속도가 빠르다.
2) 단점
- 저급 언어의 특징 때문에 고급 언어보다 배우기 어렵다.
- 시스템 자원을 직접 제어할 수 있기 때문에 프로그래밍에 세심한 주의를 기울여야 한다.
- 표준
1989년, ANSI(American National Standards Institute)에서 표준화 작업을 시작했다. 현재는 ISO / IEC(International Organization for Standardization / International Electrotechnical Commission)에서 표준화를 담당하고 있다.
C 언어의 최신 표준은 ISO/IEC 9899:2011, 줄여서 C11이라고 부른다.
C 프로그래밍
프로그래밍(programming)
프로그래밍이란 어떤 목적에 맞게 설계된 알고리즘을 프로그래밍 언어를 사용하여 프로그램을 작성하는 과정을 말한다.
작성된 프로그램은 실행 파일(executable file)로 변환되어야 실행할 수 있다.
▲C 언어의 실행 파일 생성 과정, TCP
-
소스 파일(source file)의 작성
프로그램을 작성하는 단계. 문법에 맞게 작성된 프로그램을 원시 파일 또는 소스 파일이라고 한다. C 언어를 통해 작성된 소스 파일의 확장자는 .c 이다. -
선행처리기(preprocessor)에 의한 선행처리
선행처리(preprocess)란 선행처리 문자(#)로 시작하는 지시문의 처리 작업을 의미한다.
선행처리기는 이러한 작업을 수행한다. 선행처리기는 코드 생성이 아닌, 컴파일러가 쉽게 작업하도록 소스 재구성의 역할만을 한다.
선행처리에 대한 자세한 내용은 선행처리기에서 다룬다. -
컴파일러(compiler)에 의한 컴파일
사람의 언어를 기계어로 바꿔주는 단계. 소스 파일을 기계어로 변환시키는 작업을 컴파일이라고 한다. 컴파일이 끝나 기계어로 변환된 파일을 오브젝트 파일(object file)이라고 하며, 확장자는 .o 혹은 .obj 이다. -
링커(linker)에 의한 링크
오브젝트 파일은 운영 체제와 인터페이스를 담당하는 시동 코드(start-up code)를 가지지 않는다. 또한 C 표준 라이브러리 파일도 포함하지 않는다.
이때 오브젝트 파일, 라이브러리 파일, 시동 코드를 합치는 작업을 링크라고 한다.
링커는 이러한 작업을 수행한다. 링크가 끝나면 하나의 새로운 실행 파일 혹은 라이브러리 파일이 생성된다.
여러 개의 소스 파일을 작성하고 링크를 통해 하나의 실행 파일로 만드는 작업을 분할 컴파일이라고 한다. 분할 컴파일에 대한 자세한 내용은 분할 컴파일에서 다룬다. -
실행 파일(executable file)의 생성
위의 과정을 모두 거치면 소스 파일은 실행 파일로 변환된다. 최근 개발 툴의 대부분은 위의 선행처리기, 컴파일러, 링커를 모두 소장하고 있어 한 번에 실행 파일을 생성한다.
실행 파일의 확장자는 .exe 가 된다.
C 프로그램의 특징
C 프로그램의 기본 구조는 다음과 같다.
#include <stdio.h> // include 문
#define TEXT "Welcome to C Programming!!" // define 문
int main() // 함수 선언
{
printf(TEXT); // 명령문
return 0; // return 값
}
// 실행 결과
Welcome to C Programming!!
이렇게 C 언어로 작성된 프로그램의 일반적인 특징은 다음과 같다.
-
기본 단위는 함수이다. **
C 프로그램은 하나 또는 그 이상의 함수(function)로 이루어진다. 또한 프로그램이 실행되면 제일 먼저 main() 함수를 찾아 호출하기 때문에 **반드시 main() 함수를 가지고 있어야 한다. -
함수 내의 명령문은 세미콜론(;)으로 끝나야 한다. **
명령문(statement)이란 함수 내에 기능을 정의하기 위해 사용되는 문장이다. 함수 내의 명령문은 언제나 위에서부터 아래로 순차적으로 실행되며, **언제나 세미콜론(;)으로 끝나야 한다.printf("C언어"); // 정상적으로 작동 printf("C언어") // 오류 발생
- 대소문자를 구분한다.
변수나 함수의 이름, 키워드, 예악어를 사용할 때, 대소문자를 구분한다. 따라서 정확히 구분하여 사용해야 한다. (특히 변수를 선언할 때 주의하자.)printf("C언어"); // 정상적으로 작동 Printf("C언어"); // 오류 발생
-
자유 형식(free-format)을 허용한다. **
문법만 맞다면, 여러 개를 한줄로 혹은 한줄을 여러 줄에 나눌 수 있다. 다만 프로그램 작성에 있어 중요한 것은 **가독성이다. 따라서 들여쓰기, 변수 설정을 신경써서 프로그램을 작성해야 한다.int func() { printf("C언어는 재밌어요!"); }
int func() { printf("C언어는 재밌어요!"); }
위의 두 예제는 정확히 같은 동작을 수행한다.
주석(comments)
코드의 이해를 돕는 설명이나 기능 등을 메모하는 용도로 작성한다. 다른 사람과 프로젝트를 공유할 때 보충을 해주거나 디버깅 목록을 적어두는 등 다양한 용도로 사용하기 때문에 주석을 달아두는 습관을 기르자.// 한 줄 주석 /* 여러 줄 주석 */
여러 주석 중첩할 때, */가 나오면 끝으로 인식하기 때문에 이에 주의하여 작성하자.
printf() 함수
printf() 함수는 C 언어의 표준 출력 함수이다. f는 formateed의 약자이며, 서식화된 출력을 지원한다는 의미이다. 서식 지정자를 통해 출력할 데이터의 서식을 지정할 수 있다.
#include <stdio.h>
int printf(const char * restrict format, ...); // printf() 함수의 원형
printf("printf() 함수는 서식 지정자를 통해 출력할 데이터의 서식을 지정할 수 있어요!\n");
printf("변수에 저장된 숫자는 %d입니다.", 10);
// 실행 결과
printf() 함수는 서식 지정자를 통해 출력할 데이터의 서식을 지정할 수 있어요!
변수에 저장된 숫자는 10입니다.
위 예제에서 int형 데이터인 10을 나타내기 위해서 ‘%d’라는 서식 지정자를 사용했고, 줄 바꿈을 하기 위해서 ‘\n’라는 이스케이프 시퀸스를 사용했다.
-
이스케이프 시퀸스(escape sequence)
특수한 문자를 프로그램에 출력하기 위해 만들어진 문자로 C 언어에서 사용되는 이스케이프 시퀸스는 다음과 같다.이스케이프 시퀸스 출력 내용 \’ 작은따옴표 \” 큰따옴표 \? 물음표 \\ 백슬래시(\) \a 경고음 \b 백스페이스(backspace) \n 줄 바꿈(new line) \r 캐리지 리턴(carriage return) \t 수평 탭(tab) \v 수직 탭(tab) \f 폼 피드(form feed) ’\‘는 백슬래시로 ‘₩’와 같다.
-
서식 지정자(format specifier)
출력할 데이터의 서식을 지정하는 데 사용하는 문자로 C 언어에서 사용되는 대표적인 서식 지정자는 다음과 같다.서식 지정자 출력 데이터 형태 %c 하나의 문자 %s 문자열 %d 부호 있는 10진 정수 %i 부호 있는 10진 정수 (%d와 동일) %f 고정 소수점으로 표현한 실수 (소수점 이하 6자리까지 표현) %o 부호 없는 8진 정수 %u 부호 없는 10진 정수 %x 부호 없는 16진 정수 (소문자 사용) %X 부호 없는 16진 정수 (대문자 사용) %e 부동 소수점으로 표현한 실수 (e-표기법) %E 부동 소수점으로 표현한 실수 (E- 표기법) %g 값에 따라 %f나 %e를 사용 %G 값에 따라 %f나 %E를 사용 %% 퍼센트(%) 기호 출력 printf("%%c를 사용한 결과 : %c\n", 'a'); // 문자 printf("%%s를 사용한 결과 : %s\n", "ABCD"); // 문자열 printf("%%f를 사용한 결과 : %f\n", 0.123456); printf("%%f를 사용한 결과 : %f\n", 0.123456789); // 소수점 6자리까지만 표현 printf("%%o를 사용한 결과 : %o\n", 123); // 8진 정수 printf("%%x를 사용한 결과 : %x\n", 123); // 16진 정수 printf("%%g를 사용한 결과 : %g\n", 0.001234); // 값에 따라 %f나 %e printf("%%g를 사용한 결과 : %g\n", 0.00001234); // 값에 따라 %f나 %e printf("%%G를 사용한 결과 : %G", 0.000001234); // 값에 따라 %f나 %E // 실행 결과 %c를 사용한 결과 : a %s를 사용한 결과 : ABCD %f를 사용한 결과 : 0.123456 %f를 사용한 결과 : 0.123457 // 반올림 %o를 사용한 결과 : 173 %x를 사용한 결과 : 7b %g를 사용한 결과 : 0.001234 %g를 사용한 결과 : 1.234e-05 %G를 사용한 결과 : 1.234E-06
e-표기법과 E-표기법에 대해서는 추후 다른 글로 정리할 것이다.
- 서식 지정자의 동시 사용
여러 개의 서식 지정자를 동시 사용하여, 여러 개의 데이터를 서로 다른 서식으로 지정할 수 있다. 단, 순서와 타입에 주의해서 작성해야 한다.
printf("저장된 정수는 %d이며, 저장된 문자열은 %s입니다.\n", 123, "C언어"); // 실행 결과 저장된 정수는 123이며, 저장된 문자열은 C언어입니다.
- 서식 지정자의 동시 사용
-
출력 필드의 폭 설정 서식 지정자의 ‘%’문자와 타입 영문자 사이에 다른 기호를 추가하여 출력 필드의 폭을 설정할 수 있다.
숫자는 오른쪽 정렬이 기본이며, 숫자 앞에 ‘-‘를 붙이면 왼쪽 정렬로 변경된다. ‘+’를 붙이면 오른쪽 정렬한 상태에서 양수에는 ‘+’기호를, 음수에는 ‘-‘기호를 붙여서 출력한다. 소수 부분의 숫자는 출력되는 소수의 자릿수를 명시한다.printf("%%d를 사용한 결과 : |%d|\n", 123); printf("%%7d를 사용한 결과 : |%7d|\n", 123); printf("%%+7d를 사용한 결과 : |%+7d|\n", 123); printf("%%+7d를 사용한 결과 : |%+7d|\n", -123); printf("%%-7d를 사용한 결과 : |%-7d|\n\n", 123); printf("%%f를 사용한 결과 : |%f|\n", 1.23); printf("%%.1f를 사용한 결과 : |%.1f|\n", 1.23); printf("%%7.2f를 사용한 결과 : |%7.2f|\n", 1.23); printf("%%+7.2f를 사용한 결과 : |%+7.2f|\n", 1.23); printf("%%-7.2f를 사용한 결과 : |%-7.2f|", 1.23); // 실행 결과 %d를 사용한 결과 : |123| %7d를 사용한 결과 : | 123| // %7d: 7칸 확보하고 오른쪽 정렬 %+7d를 사용한 결과 : | +123| // %d가 양수: + %+7d를 사용한 결과 : | -123| // %d가 음수: - %-7d를 사용한 결과 : |123 | // %-7d: 7칸 확보하고 왼쪽 정렬 %f를 사용한 결과 : |1.230000| %.1f를 사용한 결과 : |1.2| // %.1f: 소수점 아래 1칸 확보 %7.2f를 사용한 결과 : | 1.23| // %7.2f: 소수점 2칸 확보하고 총 7칸 확보 %+7.2f를 사용한 결과 : | +1.23| // %f가 양수: + %-7.2f를 사용한 결과 : |1.23 | // %-7.2f: 왼쪽 정렬
이 부분은 해보면서 익히는 것이 제일 좋을 것이다.
간단하게 요약하자면 일의 자리 숫자는 확보 칸수, 소수점 첫째 자리는 소수점 아래 확보 칸수, ’-‘는 왼쪽 정렬, ’+’는 부호 표시이다.
scanf() 함수
scanf() 함수는 C 언어의 표준 입력 함수이다. printf() 함수와 비슷하지만 이 함수는 사용자의 입력을 받는 함수이다.
#include <stdio.h>
int scanf(const char * restrict format, ...); // scanf() 함수의 원형
#include <stdio.h>
int main(void)
{
int num01, num02; // 메모리 할당 -> 변수 선언
printf("첫 번째 정수를 입력하세요 : ");
scanf("%d", &num01);
printf("두 번째 정수를 입력하세요 : ");
scanf("%d", &num02);
printf("입력하신 두 정수의 합은 %d입니다.\n", num01 + num02);
return 0;
}
// 실행 결과
첫 번째 정수를 입력하세요 : 10 // 사용자 입력
두 번째 정수를 입력하세요 : 20
입력하신 두 정수의 합은 30입니다.
데이터 입력을 받기 위해서는 데이터 타입에 해당하는 메모리를 할당받아야 한다. 프로그램에 의해 이름을 할당받은 메모리 공간을 변수(variable)라고 한다.
‘&’는 주소 연산자라고 하며, 입력받은 데이터를 주소 연산자 뒤에 나오는 변수에 저장하라는 의미이다. 변수에 대한 자세한 내용은 변수에서 다룬다. 주소 연산자에 대한 자세한 내용은 포인터에서 다룬다.
-
서식 지정자의 동시 사용 printf() 함수와 마찬가지로 scanf() 함수도 서식 지정자를 동시 사용하여, 여러 데이터를 서로 다른 서식으로 입력받을 수 있다. 입력받는 데이터의 구분은 공백(줄 바꿈, 탭, 띄어쓰기 등)을 기준으로 삼는다.
#include <stdio.h> int main(void) { int num01, num02; scanf("%d %d", &num01, &num02); // 띄어쓰기로 구분하여 데이터 받음. ... }
-
double형 실수의 입력 scanf() 함수로 float형 실수를 입력받을 때는 ‘%f’를 사용하면 된다. 하지만 double형 실수를 입력받을 때는 ‘%lf’를 사용해야 한다.
#include <stdio.h> int main(void) { float num01; double num02; // double형 변수 printf("두 개의 실수를 입력하세요 : "); scanf("%f %f", &num01, &num02); // 올바르지 않은 서식 지정자 printf("입력하신 두 실수는 %f와 %f입니다.\n", num01, num02); printf("입력받은 두 실수 중 두 번째 double형 변수에는 전혀 다른 값이 저장되었습니다.\n\n"); printf("다시 한 번 두 개의 실수를 입력하세요 : "); scanf("%f %lf", &num01, &num02); // 올바른 서식 지정자 printf("입력하신 두 실수는 %f와 %f입니다.\n", num01, num02); printf("이번에는 두 실수 모두 제대로 저장되었습니다.\n"); return 0; } // 실행 결과 두 개의 실수를 입력하세요 : 1.2 3.4 입력하신 두 실수는 1.200000와 0.000000입니다. 입력받은 두 실수 중 두 번째 double형 변수에는 전혀 다른 값이 저장되었습니다. 다시 한 번 두 개의 실수를 입력하세요 : 1.2 3.4 입력하신 두 실수는 1.200000와 3.400000입니다. 이번에는 두 실수 모두 제대로 저장되었습니다.
추가 및 수정
- 정리할 주제
- C11과 C99의 차이점
- 폼 피드
- e-표기법, E-표기법
- 출력 필드의 폭 설정 세분화
- 관련 문제 및 오류
Leave a comment