**C**는 1972년 켄 톰슨과 데니스 리치가 벨 연구소에서 일할 당시 새로 개발된 유닉스 운영 체제에서 사용하기 위해 개발한 프로그래밍 언어이다. 켄 톰슨은 BCPL언어를 필요에 맞추어 개조해서 "B"언어(언어를 개발한 벨 연구소의 B를 따서)라 명명했고, 데니스 리치가 이것을 개선하여 C 언어가 탄생했다. 유닉스 시스템의 바탕 프로그램은 모두 C로 작성되었고, 수많은 운영 체제의 커널 또한 C로 만들어졌다. 오늘날 많이 쓰이는 C++는 C에서 파생된 객체 지향형 언어이다.

이는 오늘날의 널리 쓰이는 거의 모든 운영 체제 커널이 C를 이용해 구현된 이유이기도 하다. 이처럼 C는 시스템 프로그램 개발에 매우 적합하지만, 응용 프로그램 개발에도 많이 쓰이기도 한다.

## 예제
이 예제는 Hello World를 출력하는 예제이다.

## 역사

### 초기 개발
C 언어의 초기 개발은 1969년부터 1973년까지 4년에 걸쳐 AT&T 벨 연구소에서 이루어졌으며, 데니스 리치의 말에 따르면, 가장 창의적인 작업이 이루어진 기간은 1972년이었다. 언어의 이름이 'C'인 이유는 그 특징이 'B' 언어에서 유래되었기 때문이며, 켄 톰슨에 의하면, B 언어는 BCPL 언어의 기본만 남긴 버전이다.

리치와 톰슨에 의해 초기에 PDP-7의 어셈블리 언어로 구현되었던 유닉스 운영체제의 개발과 C 언어의 기원은 밀접하게 연관되어 있다. 결국 그들은 유닉스 운영체제를 PDP-11로 포팅하기로 결정하였다. PDP-11의 기능의 일부, 특히 바이트 접근기능을 활용하지 못하는 B 언어의 부족함이 C 언어의 초기 버전의 개발을 이끌었다.

유닉스의 초기 PDP-11 버전은 어셈블리로 개발되었다. 1973년에

### K&R C
1978년에 브라이언 커니핸과 데니스 리치가 ''The C Programming Language''라는 책의 초판을 출간했다. 커니핸과 리치의 앞 글자만 따서 C 프로그래머들에게는 "K&R"로 불리는 이 책은, 비공식적이지만 오랫동안 C의 규격과 같은 역할을 했다. 그리하여, 이 책에서 서술하는 C의 판이 "K&R C"란 명칭으로 불리게 되었고, 이 책의 2판에서는 후의 ANSI C 표준을 다루게 되었다.

K&R에서 다음과 같은 기능이 등장한다.

### C99
C 언어 표준이 상대적으로 정적으로 남아 있었던 동안, C++는 표준화를 위하여 계속 진화하고 있었다. 1995년에 1990년의 C 표준에 대한 규약 수정안 1이 출판되었는데, 이는 약간의 세부 사항을 교정하고 국제적 문자 세트에 대한 보다 확장된 지원을 위한 것이었다. C 표준은 1990년대 후반에 더 개정되어, 1999년 ISO/IEC 9899:1999가 출간되었고, 여기서 명시한 규범을 흔히 C99라 부른다. 이는 기술적 교정에 의하여 현재까지 3번의 수정이 있었다. 국제 C 표준은 실무 그룹 ISO/IEC JTC1/SC22/WG14에 의해 관리되고 있다.

### C11
2011년 ISO/IEC 9899:2011이 출간되었고, 간단하게 C11라고 부른다. C11이 나오기 전까지의 개발 버전을 C1X라고 부른다. 최종 개발 버전은 2011년도 4월 N1570이었다.

### C17
2018년 ISO/IEC 9899:2018이 출간되었으며, 간단하게 C17이라고 부른다.

## 문법
C는 C 표준에 의해 규정되는 형식 문법을 갖고 있다. 포트란 77과 같은 언어와 달리, C 소스코드는 free-form 언어로써 형식 코드에 공백을 마음대로 넣을 수 있다.

### 포인터
선언문에서 가리키고자 하는 변수의 자료형을 맞추어 변수명 앞이나 자료형 뒤나 그 중간에 *(별표)를 붙이면(char* a; == int * pa; == double *exm;) 포인터 변수가 된다.

이렇게 선언된 포인터 변수가 실행문에서는, 일반 자료형 변수를 선언문에서 int a;라고 선언하여 변수 a가 정수형이라고 선언하고, 실행문에서는 int를 안 쓰고 변수명 a만으로 사용하듯이, *을 빼고 변수명만 사용하여 처음 접하는 초보자들이 *이 없어 혼동할 수 있으니 선언문에서와 실행문에서의 사용을 구분해야 한다.

중요한 조건은 자료형을 동일형으로 유지해야 한다. 포인터의 사용목적은 어느 변수를 그 변수명으로 가리키지 않고 그 주소값으로 가르켜서 그 변수의 값(자료값)을 간접참조(역참조)하는 것이므로 정수형 4 바이트 변수를 가르켰는데 같은 변수명이라도 문자형이나 실수형 변수에 연결되어 간접참조하여 값을 읽어오면 기억공간(memory)의 크기가 다르므로 문자형의 1 바이트 이후의 3 바이트를 더 읽거나, 실수형 8 바이트 내의 4 바이트만을 읽어오므로 크기(바이트 수)가 다를 뿐만 아니라 기록되어 있는 내용(값)이 다르므로 자료형이 가리켜지는 변수와 포인터 변수가 같아야 한다.

일반 변수의 주소(주소값)을 알아보려면 변수명에 &를 붙이면 된다(&a). 이것은 포인터가 가진 주소이므로 int a;로 정수형 변수를 선언했으면 같은 자료형 정수형으로 int *pa;로 a를 가리키는 포인터 pa를 선언하면 실행문에서는 pa == &a이다.

실행문에서 *은 일반 연산자로는 곱셈을 하고, 참조 연산자로는 해당 주소의 값(자료값)을 간접참조(역참조)하므로 *&a == *pa이다. 결국 a == *&a == *pa이다. (값이 같다는 의미로 == 를 사용)

교체(swap)함수에서 대표적으로 간접참조(call by reference)하는 경우처럼 *pa = xx로 포인터에 참조 연산자를 붙여 값을 참조한다는 표시를 하고 일반 변수의 값을 할당할 때와 같이 대입 연산자 =를 이용하여 간접참조로 가르킨 변수의 값을 xx로 변경한다.

위의 설명을 간략히 하면 아래와 같다.

포인터 - 주소값(간접참조하기 위한 변수의 주소)을 저장하는 변수

포인터 선언 - 선언문에서 주소를 저장하는 변수와 같은 자료형 명시하고 별을 변수명 앞에 붙여 표시

포인터 사용 - 실행문 내에서는 별표 없이 변수명 만 사용(일반 변수들을 선언문에서 자료형 지정하고 실행문에서 변수명 만 사용과 동일)

주소 - 공간의 첫주소(첫주소값)를 말하며 문자형 자료는 1 바잍이니 그 자체, 정수형 자료를 갖는 변수의 주소는 4 바잍의 첫주소가 전체 4 바잍의 공간을 의미, 이중 실수형 자료를 갖는 변수의 주소는 8 바잍의 첫주소가 전체 8 바잍의 공간을 의미, 표시

직접참조: 변수에 접근하여 자료값을 읽거나(복사하거나) 변경

간접참조: 변수의 주소를 통해 자료값을 복사하거나 변경

int exp_a;

int * exp_a_p; 

exp_a = 12;

exp_a_p == &exp_a;

exp_a_p == *&exp_a == exp_a == 12;

변수 주소 - 주소 연산한(주소 연산자&를 붙인) 변수명, &exp_a

1. 자료값(내용물) - 변수에 대입된 자료

2. 연산 결과 - (자료가 담긴) 해당 변수의 (기억공간의) 주소

3. 연산 목적 - 주소를 통해 해당 자료형의 공간 표시

포인터 exp_a_p - 간접참조하기 위한 변수의 주소를 저장한 변수

1. 자료값(내용물) - 가리키는 해당 자료형 자료의 시작 주소, 첫주소

2. 목적 - 가리킨 주소를 통해 기억공간을 간접참조하여 자료를 복사하거나 변경

3. 조건 - 간접참조가 목적이므로 지적한 변수와 자료형이 일치 필요

가르킴, 지시, 지적, pointing = 주소, 주소값 저장(보유)

가리키는 것, 지적 대상은 목적에 따라 자료, 자료값이기도 하고 공간이기도 함

1. 지적된 해당 자료형의 변수에 저장된 자료값을 참조(복사)하려면 실행문 우변에 위치(r value)하여 참조 연산자 별을 붙여 지적하는 주소에(를 통해) 접근하여 자료값을 간접참조(복사)

2. 지적된 해당 자료형의 변수의 공간에 접근하여 자료를 참조하려면 실행문 좌변에 위치(l value)하여 참조 연산자 별을 붙여 지적하는 주소인(주소를 통해) 공간에 접근하여 자료값을 간접참조(변경)

대상에 접근하여 참조(사용)하기 위해 참조 연산자 별 표시

역할 구분

int * pa = &a; 선언시 선언문에 변수 a의 주소를 포인터 변수 pa에 저장

포인터 변수 pa가 a의 주소 &a를 저장하고 있으므로 pa == &a

pa는 a의 주소 &a를 통해 간접참조한 a의 자료값이므로 *pa == *&a == a

&pa는 포인터 변수 pa 자체의 주소, 다중 포인터에서 사용 scanf에서 입력받아 변수 a에 직접 저장할 수 없어 그 주소 &a를 통해 넣음

scanf에서 입력받아 변수 a에 직접 저장할 수 없어 그 주소 &a를 통해 넣음

배열명 - 배열의 첫주소인 상수

## 메모리 관리
OS에서 응용 프로그램을 실행하거나, CPU의 프로그램을 실행하기 위해 여러 가지 영역으로 나누어 메모리를 할당하고 이를 메모리에 올려 실행한다.

C 언어로 개발된 프로그램은 메모리 입장에서 다음과 같은 할당 영역으로 나누어 생각할 수 있다.

CPU를 사용하여 개발하여 장치에 넣어 코드를 실행할 때, 힙 영역을 많이 사용하지는 않는다. 따라서 필요 없다면 메모리 공간을 할당할 필요도 없고 힙관리 프로그램 코드(함수를 개발툴에서 라이브러리 형태로 제공)도 필요하지 않는다. 만약 malloc 등의 함수를 사용하면, 힙 영역을 사용하겠다는 의미 이기 때문에 힙 영역을 개발자가 선언하여 관리 해야 한다. 이 때 힙관리 프로그램 코드는 자동으로 링크 된다. 물론 저 사양의 CPU 경우, 이 함수를 제공하지 않을 수 있는 컴파일러도 있을 수 있다.

### 변수와 메모리 맵
C 언어 작성된 코드는 컴파일 과정과 링크 과정을 거치면 실행 파일이 만들어진다. 변수는 여러 가지 특성이 있다.

int count = 4;
char name[50] = "홍길동";
char tel[256];

int getTel(char *pstr)
 static char buff[1024];
 gets(buff);
 strcpy;
 return strlen(pstr);

int main
 char *paddr;

 printf;
 getTel(tel);
 printf;
 paddr = (char*) malloc(1024);
 if (!paddr)
 return -1;
 int scount;
 char *piaddr = paddr;
 for  {
 putchar(*piaddr);
 if (*piaddr == '\r')
 break;
 printf;

 free(paddr);
 return 0;

이 프로그램 예에서 변수 별로 분리하면 다음과 같은 특성의 변수로 나눌 수 있다.
char name[50] = "홍길동";
static char buff[1024];
"전화 = %s\n" 
"주소 = %s\n" 
char *pstr;
int scount;
char *piaddr;
Notes:

각 특성별로 나누어 그룹을 지어 메모리에 배치 하는데, 이것을 링커가 한다. 이렇게 그룹은 나누는 것을 세그먼트(SEGMENT) 또는 섹션(SECTION)이라는 단어를 사용한다.

위의 그룹은 가장 기본적인 내용만을 표시 한 것이다. CPU와 컴파일 마다 다르다. 어떤 컴파일러는 더욱 세밀히 하기도 한다. 그리고 각 세그먼트 이름도 다르다.

Visual Studio의 맵 이름 예

컴파일마다 각 세그먼트 이름과 구조가 다르지만, 예를 들어 중요한 세그먼트만 표시하였다. TEXT와 CONST는 ROM/FLASH에 배치해도 되는 변하지 않는 세그먼트이므로 같은 부류이고, CPU를 설계하고 코드를 직접 쓰는 경우 ROM/FLASH을 이용한다.

거의 모든 툴에서 이 맵을 파일로 만들어 준다. 물론 옵션으로 설정을 해야하는 경우도 있지만 구조를 얻을 수 있다. 함수와 변수의 위치와 이름 등을 확인할 수 있고, 각각의 세그먼트 크기 등의 데이터를 알 수 있다. 실제 CPU를 다루는 C 언어에서 이런 정보는 중요하다. 내가 사용하는 MCU의 메모리는 얼마나 사용하는지 등을 확인할 필요가 있기 때문이다.

## 라이브러리
C 언어 함수는 표준함수가 있고, 개발 툴에서 제공하는 함수가 있다. 여러 가지 부류가 있고 특성 별로 나누어 lib 파일로 코드를 제공하고 헤더파일로 선언을 알 수 있다.

### C 표준 라이브러리
C 표준 라이브러리는 함수 형태와 기능이 정해져 있기 때문에 개발툴별 같다는 특징이 있다.

### ISO C 라이브러리 헤더
Contains functions used to classify characters by their types or to convert between upper and lower case in a way that is independent of the used character set . -->
Contains defined constants specifying the implementation-specific properties of the floating-point library, such as the minimum difference between two different floating-point numbers (-->
Contains defined constants specifying the implementation-specific properties of the integer types, such as the range of numbers which can be represented (-->
For -->
For computing common mathematical functions.-->
Declares the macros -->
For accessing a varying number of arguments passed to functions.-->
Provides the core input and output capabilities of the C language. This file includes the venerable -->
For performing a variety of operations, including conversion, pseudo-random numbers, memory allocation, process control, environment, signalling, searching, and sorting.-->
For manipulating wide streams and several kinds of strings using wide characters - key to supporting a range of languages.-->

## 개발 도구

### GCC
-->
유닉스 계열(리눅스)의 시스템에서 주로 사용하는 C/C++ 언어 개발 도구이다. 리눅스의 OS을 제 컴파일하거나, 각종 응용 프로그램 개발에 사용한다. 또한 X-Windows의 개발 도구로도 사용할 수 있다.

전자 장치의 개발 시 임베디드 OS 포팅에서, 리눅스 커널이나 리눅스 커널 기반으로 하는 OS 커널 자체를 개발하는 도구로 사용한다. 리눅스 커널 기반 임베디드에서 실행되는 응용 프로그램 역시 gcc을 많이 사용한다.

#### make
여러 파일들끼리의 의존성과 각 파일에 필요한 명령을 정의함으로써 프로그램을 컴파일할 수 있으며 최종 프로그램을 만들 수 있는 과정을 서술할 수 있는 표준적인 문법을 가지고 있고, 구조로 기술된 파일(주로 Makefile이라는 파일명)을 [make]가 해석하여 프로그램 빌드를 수행하게 된다.

#### Cygwin
gcc을 윈도우에서 실행할 수 있도록 재 포팅한 것이다.

#### MinGW
Cygwin에서 분화 된 gcc 기반 개발 라이브러리이다.

### 이클립스
이클립스는 다양한 언어와 다양한 OS에서 실행되는 IDE이다. 따라서 여러 가지 상황에서 다양하게 적용할 수 있다.

#### Eclipse IDE for C/C++ Developers
C/C++언어를 제공하는 IDE으로 리눅스의 경우 기존의 gcc을 사용할 수 있도록 연결 설정만 하면 된다.

윈도우에서 gcc와 연결하여 C/C++ 언어를 사용하여 프로그램을 개발 할 수 있다. MinGW는 다양한 언어를 지원하므로 다른 언어로도 이클립스와 연결하여 개발 도구로 사용할 수 있다.

### 마이크로소프트 비주얼 스튜디오
마이크로소프트에서 개발, 판매하는 마이크로소프트 윈도우 환경에서 작동하는 개발도구이다. 현재는 C 뿐만 아니라 C++, C# 등 다양한 언어를 지원하고 있지만 초기의 마이크로소프트 개발 도구는 C 언어로부터 출발하였다. 비주얼 스튜디오로는 윈도우 API를 이용한 GUI 프로그램, 명령 줄 인터페이스 환경으로 실행되는 Windows Console Application, 윈도우 서비스, 동적 링크 라이브러리 등의 형태로 소프트웨어를 개발할 수 있고, 최근 버전에서는 모바일 응용 소프트웨어 개발도 지원한다.

비주얼 스튜디오에서 사용 가능한 소프트웨어 개발 키트와 라이브러리는 다음과 같다.

#### C 표준 라이브러리
표준 C에서 정의하는 라이브러리 함수를 거의 대부분 그대로 사용할 수 있다.

#### Windows SDK
윈도우 운영체제의 API를 사용할 수 있게 해주는 툴킷이다. 응용프로그램에서 사용 가능한 윈도우 운영체제의 기능은 Windows SDK를 통해 제공된다. 초기에는 C가 기본 언어였으나, 최근에는 C#, C++ 등의 언어 툴킷도 제공한다. 예전에는 Win32 SDK라고 불리었다.

#### MFC
윈도우 개발에 필요한 Windows API를 클래스로 래핑한 C++ 라이브러리이다.

#### DirectX
윈도우에서 주로 게임 등을 개발할 때 사용하는 툴킷이다. 고속의 화면 제어, 음성지원, 3D 등을 지원한다.

CODEBLOKES

그럭저럭한 툴

## 디버깅
보통 소프트웨어 개발에서 디버깅의 가장 일반적인 방법은 두가지이다.

### GDB
GCC을 기반으로 하는 디버깅 도구이다. 따라서 유닉스 계열에서 가장 일반적으로 실행된다.

#### 응용 프로그램 디버깅
GCC 옵션을 디버깅이 되도록 설정하면 디버깅 테이블을 만든다. gdb 실행 중에 이것을 사용한다. GDB을 실행하여 응용 프로그램을 실행하면서 break, 변수, 함수 등의 디버깅을 할 수 있다.

#### 원격 디버깅
GCC에서 gdb는 서버 구조를 사용할 수 있다. gdb-server을 설치하면 네트워크를 통해 디버깅 환경을 구성할 수 있다. 예를 들어 임베디드 개발 시 리눅스 커널을 포팅하고, 해당 리눅스 시스템에 gdb-server를 설치하면 다른 환경에서 이를 통해 응용 프로그램을 디버깅 할 수 있다. 임베디드의 많은 경우 자신의 시스템에서는 디버깅이 만만치 않다. 따라서 원격으로 gdb의 실행 결과를 전송 할 수 있고 이 정보를 바탕으로 이클립스와 같은 IDE와 연동할 수 있다. 보통 리눅스 기반의 임베디드 개발 환경은 이클립스 C++를 사용할 수 있는데, 이것과 결합할 수 있다.

#### 커널 디버깅
원격 디버깅 모드는 리눅스 커널에 사용되는 소스 수준의 디버거인 KGDB에서도 사용된다. KGDB를 사용하면 커널 개발자는 일반 응용 프로그램과 마찬가지로 커널을 디버깅할 수 있다.

### IDE 디버깅
비주얼 스튜디오나 이클립스 등의 도구 들은 기본적으로 디버깅 방법을 제시한다. 이클립스 디버깅은 GDB와 연동해서 구성할 수 있다.