전처리기

전처리기는 #으로 시작하는 예약어를 뜻합니다. 전처리기는 조건에 따라 복사 붙여넣기 된 코드를 출력합니다. 일반적으로 전처리기가 끝난 코드는 (#include로 인해서) 수백, 수천, 수만줄에 이르기도 합니다. 일반적으로 컴파일러는 전처리 후 파일을 생성하지 않습니다. 이는 컴파일 옵션을 조절하여 강제로 생성하게 할 수 있습니다.

gcc -E source.c -o output.i

#include

C언어는 code파일(.c 또는 .cpp)파일과 header파일(.h;헤더)을 쌍(pair)으로 준비합니다. c파일에는 코드의 내용이, header파일에는 개요가(함수/변수 등의 선언) 포함하고 있습니다.

#include <stdio.h>  // 등록된 라이브러리 폴더의 위치들 중에서 검색
#include "myHeader.h"  // 현재 폴더를 기준으로
#include "../lib/yourHeader.h"  // 상대 경로 지정
컴파일 옵션
gcc -I /path/to/include/dir source.c -o output

문제는 어떤 header는 여러 파일에서 참조되면서 의도하지 않게 중복 될 수 있다는 것입니다. 중복 선언되게 되면 컴파일러는 잘못된 코드로 인식하여 에러를 출력합니다. 만약 다음과 같이 선언된다면, (어느 파일에서 최초로 호출 될 지는 알 수 없지만,) 최초로 호출되었을 때, __STDIO_H__가 정의되고 이후 정의될 때는 코드 전체가 스킵되는 효과를 볼 수 있을 것입니다.

stdio.h
#ifndef __STDIO_H__  // 만약 인용된 적이 없다면
#define __STDIO_H__  // 지금 인용
  ...  // 내용
#endif

#define

단순 출력
#define GREETING "good morning"
printf("greeting : %s\n", GREETING); // greeting : good morning
변수1 출력
#define var(x) x + 1
printf("var(3) : %d\n", var(3)); // XXX(3) : 4
변수2 출력
#define MIN(x, y) (x > y ? y : x)
printf("MIN(3,4): %d\n", MIN(3, 4)); // MIN(3,4): 3
매크로를 이용한 출력
#define log(x) printf("LOG(%d)\t: %s", __LINE__, x)
log("매크로 출력\n"); // LOG(17) : 매크로 출력

일부 매크로macro는 시스템에 미리 정의되어 바로 사용할 수 있습니다.

메크로 대체어
__FILE__ 현재 파일명
__LINE__ 현재 라인
__DATE__ 시스템 날자
__TIME__ 시스템 시각
__func__ 현재 함수
변수명 가져오기
#define out(x) printf(#x " = %d\n", x)
out(constVar); // constVar = 1
배열명 가져오기
#define Aout(x, n) printf(#x "[%d] = %d\n", n, x[n])
for (int i = 0; i < 5; i++) {
  a[i] = i;
  Aout(a, i); // a[0] = 0, a[1] = 1 ...
}

volatile

컴파일 옵션으로 최적화를 수행 할 수 있습니다. 다만, 기본 옵션은 최적화를 수행하지 않습니다.

예시
gcc -O1 source.c -o output

volatile 키워드는 강제적으로 최적화를 수행하지 않도록 지정합니다. 아래 코드는 임베디드 센서를 읽는 코드로 sensor의 값이 로직과 관계없이 변경 될 수 있습니다.

int main() {
  volatile int sensor = 1;

  printf("Sensor : %d\n", sensor);
  printf("Sensor : %d\n", sensor);
  printf("Sensor : %d\n", sensor);
}

extern

외부의 파일을 추가 할 때, 컴파일러에게 라이브러리가 추가 될 예정임을 알려주는 예약어입니다.

예시
extern void fnStaticLib();

라이브러리 파일

운영체제 에디터/컴파일러 파일형식
Windows Visual Studio 2022 ... .lib
linux VSCode, gcc .a

Visual Studio에서 .lib파일 생성하기

VScode에서 .a파일 생성하기

object파일 생성
gcc -c StaticLib.cpp
archive파일 생성
ar rcs StaticLib.a StaticLib.o
실행 파일 생성
gcc -c 7_04_Extern.cpp -o 7_04_Extern.o
gcc -o 7_04_Extern 7_04_Extern.o StaticLib.a
또는
gcc -o 7_04_Extern 7_04_Extern.cpp StaticLib.a
실행
7_04_Extern.exe

inline

프로그램 수행 중 함수가 호출되면, 함수가 할당된 영역으로 이동 후에 함수 기능이 완료되면 호출위치로 돌아옵니다. 이렇게 구성하면 함수가 1개만 존재하면 됩니다.
 inline 예약어가 선언되면, 함수가 재사용되지 않습니다. 호출되는 위치에 함수의 내용이 직접 기술되기 때문에 메모리를 손해를 보지만, 성능을 개선 할 수 있습니다.

inline int add(int a, int b)
{
  return a + b;
}

Math

math.h를 #include하면 수학함수를 추가 할 수 있습니다.

random

stdlib.h을 #include하면 rand함수를 추가 할 수 있습니다.

rand();

Malloc

malloc함수는 지정한 크기의 메모리를 동적으로 할당한 뒤, void *로 반환합니다.

pArr = (char*)malloc(szArr);

File

..._s는 안정성을 추가한 함수입니다.(권장)

FILE *pFile;
char Buf[100];

// 파일을 엽니다.
fopen_s(&pFile, "log.txt", "a+");

if (pFile == NULL) {
  puts("파일을 열 수가 없습니다!");
  return false;
} else {
  puts("파일을 성공적으로 열었습니다!");
}

// 파일을 읽어옵니다.
while (fgets(Buf, sizeof(Buf), pFile) != NULL) {
  printf("%s", Buf);
}

// pFile에 추가할 문구를 Buf에 작성합니다.
sprintf_s(Buf, sizeof(Buf), "%s %s(%d): %s\n", __DATE__, __TIME__, __LINE__, __FILE__);
printf("추가 문구 : %s\n", Buf);

fputs(Buf, pFile); // 문구를 추가합니다.

// 파일을 닫습니다.
if (fclose(pFile) != 0) {
  puts("파일을 닫을 수가 없습니다!");
  return false;
} else {
  puts("파일을 성공적으로 닫았습니다!");
}
모드 설명
r (read mode) 읽기 전용 모드
w (write mode) 쓰기 전용 모드
a (append mode) 추가 모드
t (text mode) 해당 파일의 데이터를 텍스트 파일로 인식하고 입출력함.
b (binary mode) 해당 파일의 데이터를 바이너리 파일로 인식하고 입출력함.
x (exclusive mode) 열고자 하는 파일이 이미 존재하면 파일 개방에 실패함.
+ (update mode) 파일을 읽을 수도 있고 쓸 수도 있는 모드

모드 예시: wx, rb, wb, wbx, ab, r+, w+, w+x, a+, r+b, rb+, a+b, ab+, w+bx, wb+x

기타

두 변수의 교환

c = b;
b = a;
a = c;

위 코드와 아래 코드는 동일한 기능을 합니다.

a ^= b
b ^= a;
a ^= b;

성능 측정

time.h를 #include하면 clock()함수를 사용할 수 있습니다. clock함수는 CPU클럭을 반환합니다.

테스테 예제
start = clock(); //시간 측정 시작
for (int i = 0; i < TIMES; i++) {
  ptr(A, B);
}
end = clock(); //시간 측정 끝
result = ((double)end - start);

간의 테스트 결과

성능 체크 중...
Swap : XOR (메모리절약) = 349.000000
Swap (메모리사용) = 291.000000
Swap : XOR [Inline] = 349.000000
Swap [Inline] = 247.000000

XOR swap방법은 퍼포먼스 시간면에서 불리하고, inline함수는 시간면에서 유리한 것을 확인 할 수 있습니다.