: 1972년 벨 연구소 Dennis Ritchie에 의해 만들어진 UNIX(유닉스) 운영체제를 위해 고안된 언어. 지금은 다양한 분야의 프로그램개발에 사용되고 있다.
- 동일하게 동작하는 표준 라이브러리(Library)함수를 프로그래머에게 제공하기 때문에 소스 코드의 변경없이 다른 컴퓨터나 운영체제에서 실행 할 수 있다.
- 특정 CPU를 가진 컴퓨터 시스템에서만 실행되는 기계 종속적인(machine-dependent)프로그램이 아닌 어떤 하드웨어든지 지원이 가능한 기계 독립적인(machine-independent) 프로그램 개발이 가능하다.
- 기능에 따라 함수 단위로 나누어 세분화시켜 모듈화된 프로그램을 만들어 중복된 코드를 최소화시키고 코드의 재사용이 가능해지며 그에 따라 프로그램 유지 관리도 효율적이게 된다.
cf) 함수란 공통된 기능을 수행하기 위한 명령어들을 하나의 독립된 단위로 모아 놓은 모듈
- 저급언어 어셈블리어의 연산기능과 고급언어의 제어구조나 기능적인 모듈을 간단한 표기법으로 제공한다.→ 간결하고 쉬운 표현으로 코드 작성이 가능하다.
- 포인터를 이용하면 메모리 주소를 직접 제어할 수 있어 효율적인 메모리 관리와 더불어 실행속도를 향상시킨다. 하지만 잘못된 사용으로 처리능력을 저하시킬 수 있으므로 신중히 사용해야한다.
cf) 포인터 : 데이터가 저장된 메모리의 주소
기계어 ← C언어 → 사람(프로그래머)
↑ 중간 매개체의 역할
요구사항 분석
→ 설계
→ 소스 코드 작성 : 파일의 확장자 .c
→ 기계어로 변환 = 컴파일(:compile) / 확장자 : .obj
2진수인 기계어로 코드를 번역 과정.
→ 실행 파일 생성 = 링크(:link)
.obj 파일을 하나의 파일로 연결 후 .exe 실행파일 생성. 링커(linker)가 이를 실행함.
→ 프로그램 실행
→ 디버깅
→ 유지보수
: 직역하자면 소스코드 컴파일 전 처리하는 일이라고 생각하면 된다.
C언어에서 제공하는 라이브러리 함수 중 표준입출력 함수가 정의되어 있는 파일을 현재 소스 코드에 포함시키라는 의미를 가진다.
- 전처리기의 시작은 #(전처리기 지시자) 기호로 시작한다. " ; " 은 붙이지 않는다.
헤더파일을 include하는 기능을 가진다. #include<stdio.h> 확장자 h를 갖는 파일(헤더파일) stdi(nput)o(utput).h
: 가장 먼저 실행되는 함수이다.
프로그램의 시작을 의미하므로 반듯이 한번만 사용되어야 한다.
: 사용하기로 미리 정해진 명령어
- 자료형, 제어문 관련, 기억클래스 관련, 기타 예약어
: 변수, 배열, 함수 등을 구분하기 위해 사용자가 직접 지정하는 이름
식별자 만들 때의 규칙
- 영문자와 숫자, 밑줄(_)만 사용 가능.
- 식별자의 첫 글자는 반드시 영문자나 밑줄(_)을 사용.
- 문자 사이에 공백 및 예약어 사용 금지.
- 모든 변수는 사용하기 전에 반드시 정의해야함.
- 영문자의 경우 대문자와 소문자는 서로 구별됨.
: 초기값 설정 시 프로그램 실행도중 변경할 수 없는 데이터.
- 문자형, 정수형, 실수형,문자열 상수가 있음.
: 값을 계산하기 위해 사용되는 기호
- 산술, 논리, 관계 연산자 등.
: 프로그램 실행에 필요한 데이터를 메모리에 저장하기 위한 저장 공간
: 변수에 넣을 데이터의 종류
- 메모리에 변수의 공간을 할당할 때 공간의 크기를 적절하게 할당하기 위해 사용.
: 어떤 데이터를 메모리에 저장하기 위해서는 저장할 데이터 공간을 확보하고 해당 위치에 접근하기 위한 이름을 컴파일러에게 미리 알려주는 행위.
int main(void) { int number_1; // 선언 : 4byte를 할당 int number_2 = 3; // 초기화 : 4byte를 할당하고 3으로 초기화 }
: 값 자체를 직접 나타내는 숫자나 문자. 컴파일러가 적당히 메모리 크기를 할당한다.
1-1 정수형 상수
: 양수, 0, 음수로 이루어진 상수를 의미하며 기본적으로 int로 인식한다.
int number_1 = 100; long number_2 = 100L;정수형 상수는 10진수 이외 8진수, 16진수로도 표현이 가능하다.
1-2 실수형 상수
: 3.14와 같이 소수점을 갖는 수를 의미한다.
1) 고정 소수점 방식
: 정수부와 소수부의 비트를 일정한 크기로 할당해 소수점의 위치를 고정시키는 방식.
Ex) 32비트를 이용한 실수 표현 : 16비트 부호를 포함한 정수 저장 + 16비트 소수부 저장
고정 소수점 방식은 편리하지만 정밀한 소수부의 표현이 힘들다는 단점이 있다.
2) 부동 소수점 방식
고정 소수점 방식과 달리 소수점이 고정되어 있지 않다.
한정된 비트를 보다 효율적으로 사용할 수 있다.123.456 → 1.23456 x 10^2 (= 1.23456e + 02) 가수부 지수부고정 소수점 방식으로 표현된 123.456을 부동 소수점 방식으로 표현을 했고 1.23455e + 02 으로 표현하는 방식을 지수형 방식이라고 한다.
1-3 문자형 상수
1) 문자 상수
: 단일인용부호(")을 이용하여 하나의 문자를 표현하는 상수.
0과 1만 이해할 수 있는 컴퓨터는 아스키코드 값을 이용해 문자를 처리한다.
그렇기에 문자형 상수는 문자로 표현 할 수도 있지만 가지고 있는 코드값인 정수('A' = 65)로 표현하는 것이 가능하다.cf) 아스키코드 제어문자 33 + 출력 가능한 문자 95 = 128개로 구성 / 7bit
2) escape 문자
: 특수한 용도로 문자를 표현하기 위해 백슬래시와 함께 사용되는 문자.
커서의 이동을 제어하거나 C언어 문법과의 구별을 위해 사용된다.
1-4 문자열형 상수
: C언어는 문자열이라는 자료형을 지원하지 않기 때문에 여러 개의 문자를 배열이나 포인트를 이용하여 묶어 사용한다.
- 이중인용부호 (")을 이용하여 표현한다.
- 문자열 상수를 메모리 공간에 저장하기 위해서는 문자열의 마지막을 나타내는 NULL문자( = \0)이 들어갈 공간까지 고려해야함으로 문자열 + 1byte 한 저장공간을 할당해야한다.
"Hello C!" : 9byte 필요
: 변수를 선언하고 초기화할 때 더 이상 해당 변수의 값을 변경할 수 없게 상수화시킴을 의미한다.
#include<stdio.h> int main(void) { const double pi = 3.14; }
: 다양한 명령어를 포함하고 있는 헤더 파일을 현재프로그램에서 사용할 수 있게 하거나 상수 등을 치환하는 등 컴파일 전 일련의 작업을 미리 처리해주는 역할.
선행처리기 사용시 주의할 점
- 반드시 # 으로 시작한다.
- 일반적으로 소스 프로그램의 첫 부분에 위치한다.
- 명령문 끝에는 세미콜론(;)을 붙이지 않는다.
- 한 줄에 하나의 명령만 사용한다.
: include문은 헤더 파일이나 사용자가 만든 다른 파일을 현재 소스코드에 포함시키기 위해 사용하는 선행처리문.
#include 선행처리기를 사용하는 방법은 2가지가 있다.#include <라이브러리 헤더> #include <stdio.h>
- 전처리기는 < > 안에 표기된 파일을 표준라이브러리가 모여 있는 디렉터리에서 찾아 현재 코드에 포함시킨다.
#include "사용자 정의 헤더" #include "/tc/lib/math.h"
- 프로그래머가 직접 만든 파일을 현재 코드에 포함시키고자 할 때 해당 파일이 있는 경로를 직접 표기해 해당 디렉터리를 검색 후 파일을 포함시킨다.
: 매크로란 일련의 명령들을 한 번의 동작으로 실행되도록 해주는 기능을 의미한다.
- 반복되는 명령어를 매크로로 만들어주면 효율적인 시스템 관리가 가능하다. 보통 반복되는 상수, 함수들을 약어로 정의해놓고 사용한다.
- 보통 일반 변수와 구분하기 위해 대문자를 많이 사용하며 중간 공백은 허용하지 않는다.
1) 매크로 상수 정의
: 숫자, 문자, 문자열 등을 특정 단어로 정의해서 사용.
- 문자열의 경우 " " 안에 값을 넣고 문자의 경우 ' ' 안에 값을 넣는다.
#define 매크로상수 숫자, 문자, 문자열 등의 값 #define MAX 1000
2) 매크로 함수 정의
: 매크로 상수처럼 치환뿐만 아니라 함수의 인자를 가져 함수처럼 사용할 수 있다.
- 실제 함수가 아니므로 함수가 호출되는 개념이 아니라 호출된 곳에 코드가 직접 삽입하는 형태로 사용이 된다. 따라서 실행 속도는 빠를지 몰라도 프로그램 크기는 커질 수 있다.
#define SUM(x, y) ((x) + (y))
: 특정조건이 만족될 때만 특정 코드를 삽입하여 컴파일 하도록 한다.
1)
#if
: 기본적인 조건부 컴파일러 지시자#include<stdio.h> #define AGE 30 int main(void) { #if(AGE == 30) printf("30살 입니다.\n"); #elif(AGE < 30) printf("30살 보다 나이가 어립니다.\n"); #else printf("30살 보다 나이가 많습니다.\n"); #endif }
2)
#ifdef← →#ifndef
: if defined(정의된 경우)의 약어로 #ifdef문 다음에 표기된 매크로가 정의되었는지의 여부를 검사한다.
#ifdef다음 매크로가 미리 정의되 있다면#ifdef와#endif사이의 문장을 삽입하고 컴파일한다.#ifndef은 반대의 개념. (if not defined)
3)
#undef
: #define에 의해 정의한 매크로를 취소하는 지시어.
- 주로 정의한 매크로의 값을 변경하기 위해 취소하고 재정의하여 사용한다.
#ifdef #ifndef #undef 예제
#include<stdio.h> #define AGE 30 int main(void) { #ifdef AGE // AGE매크로 정의 되어있는지 판단. printf("30살 입니다.\n"); #endif ------------- #ifndef NAME // AGE매크로 정의 되어있지 않은지 판단. printf("이름은 밝히지 않았습니다.\n"); #endif ------------- #undef AGE // 매크로 취소 #define AGE 40 // 재정의 printf("아니군요. 당신은 %d세입니다.\n", AGE); } < output > 30살 입니다. 이름은 밝히지 않았습니다. 아니군요. 당신은 40세입니다.