์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐Ÿ”ง C์–ธ์–ด ์ „์ฒ˜๋ฆฌ๊ธฐ์™€ ๋งคํฌ๋กœ๋กœ ๋งˆ๋ฒ•์ฒ˜๋Ÿผ ์ฝ”๋“œ ์ƒ์„ฑํ•˜๊ธฐ! ์กฐ๊ฑด๋ถ€ ์ปดํŒŒ์ผ ์™„์ „์ •๋ณต ๊ฐ€์ด๋“œ

๐Ÿ”ง C์–ธ์–ด ์ „์ฒ˜๋ฆฌ๊ธฐ์™€ ๋งคํฌ๋กœ๋กœ ๋งˆ๋ฒ•์ฒ˜๋Ÿผ ์ฝ”๋“œ ์ƒ์„ฑํ•˜๊ธฐ! ์กฐ๊ฑด๋ถ€ ์ปดํŒŒ์ผ ์™„์ „์ •๋ณต ๊ฐ€์ด๋“œ

์ปดํŒŒ์ผ ์ „์— ์ฝ”๋“œ๋ฅผ ๋ณ€์‹ ์‹œํ‚ค๋Š” ์ „์ฒ˜๋ฆฌ๊ธฐ์˜ ๋ชจ๋“  ๊ฒƒ

์•ˆ๋…•! ๐Ÿ‘‹ ์˜ค๋Š˜์€ C์–ธ์–ด๋ฅผ ๋‹ค๋ฃจ๋Š” ๊ฐœ๋ฐœ์ž๋ผ๋ฉด ๋ฐ˜๋“œ์‹œ ์•Œ์•„์•ผ ํ• , ๊ทธ๋Ÿฐ๋ฐ ์˜์™ธ๋กœ ์ œ๋Œ€๋กœ ํ™œ์šฉํ•˜์ง€ ๋ชปํ•˜๋Š” ์ „์ฒ˜๋ฆฌ๊ธฐ(Preprocessor)์™€ ๋งคํฌ๋กœ์— ๋Œ€ํ•ด ๊นŠ์ด ์žˆ๊ฒŒ ํŒŒํ—ค์ณ๋ณผ ๊ฑฐ์•ผ. ๋งˆ์น˜ ์š”๋ฆฌ์‚ฌ๊ฐ€ ์žฌ๋ฃŒ๋ฅผ ์†์งˆํ•˜๋“ฏ, ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ฝ”๋“œ๋ฅผ ์š”๋ฆฌํ•˜๊ธฐ ์ „์— ์ „์ฒ˜๋ฆฌ๊ธฐ๊ฐ€ ๋จผ์ € ์ฝ”๋“œ๋ฅผ ๋‹ค๋“ฌ์–ด์ฃผ๋Š” ๊ณผ์ •์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋ผ! ๐Ÿณ

์ „์ฒ˜๋ฆฌ๊ธฐ๋Š” ์ปดํŒŒ์ผ ๊ณผ์ •์—์„œ ๊ฐ€์žฅ ๋จผ์ € ์‹คํ–‰๋˜๋Š” ๋‹จ๊ณ„๋กœ, ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ์‹ค์ œ๋กœ ์ปดํŒŒ์ผํ•˜๊ธฐ ์ „์— ํ…์ŠคํŠธ ์ˆ˜์ค€์—์„œ ๋ณ€ํ™˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ด. ์ด๊ฒŒ ์™œ ์ค‘์š”ํ•˜๋ƒ๊ณ ? ์ด๊ฑธ ์ž˜ ํ™œ์šฉํ•˜๋ฉด ์ฝ”๋“œ์˜ ์žฌ์‚ฌ์šฉ์„ฑ์„ ๋†’์ด๊ณ , ํ”Œ๋žซํผ๋ณ„๋กœ ๋‹ค๋ฅธ ์ฝ”๋“œ๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ , ๋””๋ฒ„๊น… ์ฝ”๋“œ๋ฅผ ์‰ฝ๊ฒŒ ๋„ฃ์—ˆ๋‹ค ๋บ๋‹ค ํ•  ์ˆ˜ ์žˆ๊ฑฐ๋“ ! ๐Ÿ’ช

์†Œ์Šค ์ฝ”๋“œ source.c ์ „์ฒ˜๋ฆฌ๊ธฐ Preprocessor ์ปดํŒŒ์ผ๋Ÿฌ Compiler #define #include #ifdef #ifndef #if #elif #else ๐Ÿ”ง โš™๏ธ โœจ

๐ŸŽฏ ์ „์ฒ˜๋ฆฌ๊ธฐ๋ž€ ๋ฌด์—‡์ธ๊ฐ€?

์ „์ฒ˜๋ฆฌ๊ธฐ๋Š” ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์‹ค์ œ๋กœ ์ฝ”๋“œ๋ฅผ ๋ฒˆ์—ญํ•˜๊ธฐ ์ „์— ์‹คํ–‰๋˜๋Š” ํ…์ŠคํŠธ ์น˜ํ™˜ ๋„๊ตฌ์•ผ. C ์ปดํŒŒ์ผ ๊ณผ์ •์€ ํฌ๊ฒŒ 4๋‹จ๊ณ„๋กœ ๋‚˜๋‰˜๋Š”๋ฐ, ์ „์ฒ˜๋ฆฌ(Preprocessing) โ†’ ์ปดํŒŒ์ผ(Compilation) โ†’ ์–ด์…ˆ๋ธ”(Assembly) โ†’ ๋งํ‚น(Linking) ์ˆœ์„œ๋กœ ์ง„ํ–‰๋ผ. ์ „์ฒ˜๋ฆฌ๊ธฐ๋Š” ์ด ์ค‘ ์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„๋ฅผ ๋‹ด๋‹นํ•˜์ง€! ๐ŸŽฌ

๐Ÿ“Œ ์ „์ฒ˜๋ฆฌ๊ธฐ์˜ ํ•ต์‹ฌ ํŠน์ง• 1. ์ปดํŒŒ์ผ ์ „์— ์‹คํ–‰๋˜๋ฏ€๋กœ ๋Ÿฐํƒ€์ž„ ์˜ค๋ฒ„ํ—ค๋“œ๊ฐ€ ์—†์Œ
2. ํ…์ŠคํŠธ ๊ธฐ๋ฐ˜ ์น˜ํ™˜์ด๋ฏ€๋กœ ํƒ€์ž… ์ฒดํฌ๊ฐ€ ์—†์Œ
3. #์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ์ง€์‹œ์ž(directive)๋ฅผ ์‚ฌ์šฉ
4. ์กฐ๊ฑด๋ถ€ ์ปดํŒŒ์ผ๋กœ ํ”Œ๋žซํผ๋ณ„ ์ฝ”๋“œ ๊ด€๋ฆฌ ๊ฐ€๋Šฅ
5. ๋งคํฌ๋กœ๋ฅผ ํ†ตํ•œ ์ฝ”๋“œ ์žฌ์‚ฌ์šฉ์„ฑ ํ–ฅ์ƒ

์ „์ฒ˜๋ฆฌ๊ธฐ ์ง€์‹œ์ž๋Š” ํ•ญ์ƒ # ๊ธฐํ˜ธ๋กœ ์‹œ์ž‘ํ•ด. ๊ทธ๋ฆฌ๊ณ  ์ค‘์š”ํ•œ ๊ฑด, ์ „์ฒ˜๋ฆฌ๊ธฐ๋Š” C ์–ธ์–ด์˜ ๋ฌธ๋ฒ•์„ ์ดํ•ดํ•˜์ง€ ๋ชปํ•œ๋‹ค๋Š” ๊ฑฐ์•ผ! ๋‹จ์ˆœํžˆ ํ…์ŠคํŠธ๋ฅผ ์ฐพ์•„์„œ ๋ฐ”๊พธ๋Š” ์—ญํ• ๋งŒ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋ผ. ๋งˆ์น˜ ์›Œ๋“œํ”„๋กœ์„ธ์„œ์˜ '์ฐพ๊ธฐ ๋ฐ ๋ฐ”๊พธ๊ธฐ' ๊ธฐ๋Šฅ์ฒ˜๋Ÿผ ๋ง์ด์•ผ. ๐Ÿ“

๐Ÿ’ก #define ๋งคํฌ๋กœ์˜ ๊ธฐ๋ณธ

๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ด๋ฉด์„œ๋„ ๊ฐ•๋ ฅํ•œ ์ „์ฒ˜๋ฆฌ๊ธฐ ์ง€์‹œ์ž๊ฐ€ ๋ฐ”๋กœ #define์ด์•ผ. ์ด๊ฑธ ์‚ฌ์šฉํ•˜๋ฉด ์ƒ์ˆ˜๋ฅผ ์ •์˜ํ•˜๊ฑฐ๋‚˜, ํ•จ์ˆ˜์ฒ˜๋Ÿผ ๋™์ž‘ํ•˜๋Š” ๋งคํฌ๋กœ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด! ๐Ÿš€

๐Ÿ”น ๊ฐ์ฒดํ˜• ๋งคํฌ๋กœ (Object-like Macro)

๊ฐ€์žฅ ๋‹จ์ˆœํ•œ ํ˜•ํƒœ์˜ ๋งคํฌ๋กœ๋กœ, ํŠน์ • ์ด๋ฆ„์„ ๋‹ค๋ฅธ ํ…์ŠคํŠธ๋กœ ์น˜ํ™˜ํ•ด์ฃผ๋Š” ์—ญํ• ์„ ํ•ด. ์ฃผ๋กœ ์ƒ์ˆ˜๋ฅผ ์ •์˜ํ•  ๋•Œ ์‚ฌ์šฉํ•˜์ง€.

#define PI 3.14159265359
#define MAX_BUFFER_SIZE 1024
#define COMPANY_NAME "TechCorp"
#define VERSION_MAJOR 2
#define VERSION_MINOR 5

int main() {
    double radius = 5.0;
    double area = PI * radius * radius;
    
    char buffer[MAX_BUFFER_SIZE];
    printf("Company: %s\n", COMPANY_NAME);
    printf("Version: %d.%d\n", VERSION_MAJOR, VERSION_MINOR);
    
    return 0;
}

์œ„ ์ฝ”๋“œ๊ฐ€ ์ „์ฒ˜๋ฆฌ๋˜๋ฉด ๋ชจ๋“  PI๋Š” 3.14159265359๋กœ, MAX_BUFFER_SIZE๋Š” 1024๋กœ ์น˜ํ™˜๋ผ. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋‚˜์ค‘์— ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ๋•Œ ํ•œ ๊ณณ๋งŒ ์ˆ˜์ •ํ•˜๋ฉด ๋˜๋‹ˆ๊นŒ ์œ ์ง€๋ณด์ˆ˜๊ฐ€ ํ›จ์”ฌ ํŽธํ•ด์ง€์ง€! ๐ŸŽจ

๐Ÿ’ก TIP: ๋งคํฌ๋กœ ์ด๋ฆ„์€ ๊ด€๋ก€์ ์œผ๋กœ ๋Œ€๋ฌธ์ž์™€ ์–ธ๋”์Šค์ฝ”์–ด๋ฅผ ์‚ฌ์šฉํ•ด. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ฝ”๋“œ๋ฅผ ์ฝ์„ ๋•Œ "์•„, ์ด๊ฑด ๋งคํฌ๋กœ๊ตฌ๋‚˜!"ํ•˜๊ณ  ๋ฐ”๋กœ ์•Œ์•„๋ณผ ์ˆ˜ ์žˆ๊ฑฐ๋“ !

๐Ÿ”น ํ•จ์ˆ˜ํ˜• ๋งคํฌ๋กœ (Function-like Macro)

ํ•จ์ˆ˜์ฒ˜๋Ÿผ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฐ›์•„์„œ ๋™์ž‘ํ•˜๋Š” ๋งคํฌ๋กœ์•ผ. ๊ด„ํ˜ธ ์•ˆ์— ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์ •์˜ํ•˜๊ณ , ๋ณธ๋ฌธ์—์„œ ๊ทธ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด.

#define SQUARE(x) ((x) * (x))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define ABS(x) ((x) < 0 ? -(x) : (x))
#define IS_EVEN(n) (((n) % 2) == 0)

int main() {
    int num = 5;
    printf("Square of %d: %d\n", num, SQUARE(num));
    
    int a = 10, b = 20;
    printf("Max: %d\n", MAX(a, b));
    printf("Min: %d\n", MIN(a, b));
    
    int negative = -15;
    printf("Absolute: %d\n", ABS(negative));
    
    printf("Is 4 even? %d\n", IS_EVEN(4));
    
    return 0;
}
โš ๏ธ ์ฃผ์˜์‚ฌํ•ญ: ๋งคํฌ๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ๋ฐ˜๋“œ์‹œ ๊ด„ํ˜ธ๋กœ ๊ฐ์‹ธ์•ผ ํ•ด! ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์—ฐ์‚ฐ์ž ์šฐ์„ ์ˆœ์œ„ ๋•Œ๋ฌธ์— ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ฌ ์ˆ˜ ์žˆ์–ด.

์ž˜๋ชป๋œ ์˜ˆ: #define SQUARE(x) x * x
์˜ฌ๋ฐ”๋ฅธ ์˜ˆ: #define SQUARE(x) ((x) * (x))

๋งŒ์•ฝ SQUARE(2+3)์„ ํ˜ธ์ถœํ•˜๋ฉด, ์ž˜๋ชป๋œ ๋ฒ„์ „์€ 2+3*2+3 = 11์ด ๋˜์ง€๋งŒ, ์˜ฌ๋ฐ”๋ฅธ ๋ฒ„์ „์€ ((2+3)*(2+3)) = 25๊ฐ€ ๋ผ!

๐Ÿ”น ๋‹ค์ค‘ ๋ผ์ธ ๋งคํฌ๋กœ

๋งคํฌ๋กœ๊ฐ€ ์—ฌ๋Ÿฌ ์ค„์— ๊ฑธ์ณ ์žˆ์„ ๋•Œ๋Š” ๋ฐฑ์Šฌ๋ž˜์‹œ(\)๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ค„์„ ์ด์–ด์ค˜์•ผ ํ•ด. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ณต์žกํ•œ ๋กœ์ง๋„ ๋งคํฌ๋กœ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด! ๐Ÿ“š

#define SWAP(a, b, type) \
    do { \
        type temp = (a); \
        (a) = (b); \
        (b) = temp; \
    } while(0)

#define DEBUG_PRINT(fmt, ...) \
    do { \
        fprintf(stderr, "[DEBUG] %s:%d:%s(): " fmt "\n", \
                __FILE__, __LINE__, __func__, ##__VA_ARGS__); \
    } while(0)

int main() {
    int x = 10, y = 20;
    printf("Before swap: x=%d, y=%d\n", x, y);
    
    SWAP(x, y, int);
    printf("After swap: x=%d, y=%d\n", x, y);
    
    DEBUG_PRINT("Values are x=%d, y=%d", x, y);
    
    return 0;
}

์—ฌ๊ธฐ์„œ do { ... } while(0) ํŒจํ„ด์„ ์‚ฌ์šฉํ•œ ์ด์œ ๊ฐ€ ๊ถ๊ธˆํ•˜์ง€? ์ด๊ฑด ๋งคํฌ๋กœ๋ฅผ ํ•จ์ˆ˜์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ํŠธ๋ฆญ์ด์•ผ. ์„ธ๋ฏธ์ฝœ๋ก ์„ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋ถ™์ผ ์ˆ˜ ์žˆ๊ณ , if๋ฌธ ๊ฐ™์€ ๊ณณ์—์„œ๋„ ์•ˆ์ „ํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฑฐ๋“ ! ๐Ÿ›ก๏ธ

๐Ÿ”€ ์กฐ๊ฑด๋ถ€ ์ปดํŒŒ์ผ์˜ ์„ธ๊ณ„

์กฐ๊ฑด๋ถ€ ์ปดํŒŒ์ผ์€ ์ „์ฒ˜๋ฆฌ๊ธฐ์˜ ์ง„์ •ํ•œ ํŒŒ์›Œ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๊ธฐ๋Šฅ์ด์•ผ! ํŠน์ • ์กฐ๊ฑด์— ๋”ฐ๋ผ ์ฝ”๋“œ์˜ ์ผ๋ถ€๋ฅผ ์ปดํŒŒ์ผ์— ํฌํ•จ์‹œํ‚ค๊ฑฐ๋‚˜ ์ œ์™ธํ•  ์ˆ˜ ์žˆ์–ด. ์ด๊ฒŒ ์™œ ์ค‘์š”ํ•˜๋ƒ๊ณ ? ๐Ÿค”

๐ŸŽฏ ์กฐ๊ฑด๋ถ€ ์ปดํŒŒ์ผ์ด ํ•„์š”ํ•œ ์ƒํ™ฉ๋“ค โ€ข ๋””๋ฒ„๊ทธ ๋ชจ๋“œ์™€ ๋ฆด๋ฆฌ์ฆˆ ๋ชจ๋“œ๋ฅผ ๊ตฌ๋ถ„ํ•  ๋•Œ
โ€ข ํ”Œ๋žซํผ๋ณ„๋กœ ๋‹ค๋ฅธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ (Windows, Linux, macOS)
โ€ข ํŠน์ • ๊ธฐ๋Šฅ์„ ์„ ํƒ์ ์œผ๋กœ ํ™œ์„ฑํ™”/๋น„ํ™œ์„ฑํ™”ํ•  ๋•Œ
โ€ข ์ปดํŒŒ์ผ๋Ÿฌ ๋ฒ„์ „์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ
โ€ข ํ…Œ์ŠคํŠธ ์ฝ”๋“œ๋ฅผ ์ž„์‹œ๋กœ ํฌํ•จ์‹œํ‚ฌ ๋•Œ

๐Ÿ”น #ifdef์™€ #ifndef

๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ์กฐ๊ฑด๋ถ€ ์ปดํŒŒ์ผ ์ง€์‹œ์ž์•ผ. ํŠน์ • ๋งคํฌ๋กœ๊ฐ€ ์ •์˜๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ , ๊ทธ์— ๋”ฐ๋ผ ์ฝ”๋“œ๋ฅผ ํฌํ•จ์‹œํ‚ค๊ฑฐ๋‚˜ ์ œ์™ธํ•ด.

#define DEBUG_MODE

#ifdef DEBUG_MODE
    #define LOG(msg) printf("[LOG] %s\n", msg)
    #define ERROR(msg) fprintf(stderr, "[ERROR] %s\n", msg)
#else
    #define LOG(msg)
    #define ERROR(msg)
#endif

int main() {
    LOG("Program started");
    
    int result = calculate_something();
    
    #ifdef DEBUG_MODE
    printf("Debug: result = %d\n", result);
    #endif
    
    if (result < 0) {
        ERROR("Calculation failed");
        return 1;
    }
    
    LOG("Program finished successfully");
    return 0;
}

์œ„ ์ฝ”๋“œ์—์„œ DEBUG_MODE๊ฐ€ ์ •์˜๋˜์–ด ์žˆ์œผ๋ฉด ๋กœ๊ทธ ๋ฉ”์‹œ์ง€๋“ค์ด ์ถœ๋ ฅ๋˜์ง€๋งŒ, ์ •์˜๋˜์–ด ์žˆ์ง€ ์•Š์œผ๋ฉด LOG์™€ ERROR ๋งคํฌ๋กœ๊ฐ€ ๋นˆ ๋ฌธ์ž์—ด๋กœ ์น˜ํ™˜๋˜์–ด ์•„๋ฌด๊ฒƒ๋„ ์ถœ๋ ฅ๋˜์ง€ ์•Š์•„! ๋ฆด๋ฆฌ์ฆˆ ๋ฒ„์ „์—์„œ๋Š” ๋””๋ฒ„๊ทธ ์ฝ”๋“œ๊ฐ€ ์™„์ „ํžˆ ์ œ๊ฑฐ๋˜๋Š” ๊ฑฐ์ง€. ๐ŸŽญ

๐Ÿ”น ํ—ค๋” ํŒŒ์ผ ์ค‘๋ณต ํฌํ•จ ๋ฐฉ์ง€

#ifndef์˜ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ์šฉ๋„ ์ค‘ ํ•˜๋‚˜๊ฐ€ ๋ฐ”๋กœ ํ—ค๋” ํŒŒ์ผ์˜ ์ค‘๋ณต ํฌํ•จ์„ ๋ฐฉ์ง€ํ•˜๋Š” ๊ฑฐ์•ผ. ์ด๊ฑธ ์ธํด๋ฃจ๋“œ ๊ฐ€๋“œ(Include Guard)๋ผ๊ณ  ๋ถˆ๋Ÿฌ!

// myheader.h
#ifndef MYHEADER_H
#define MYHEADER_H

// ํ—ค๋” ํŒŒ์ผ์˜ ๋‚ด์šฉ
typedef struct {
    int x;
    int y;
} Point;

void print_point(Point p);
int calculate_distance(Point p1, Point p2);

#endif // MYHEADER_H

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๊ฐ™์€ ํ—ค๋” ํŒŒ์ผ์ด ์—ฌ๋Ÿฌ ๋ฒˆ ํฌํ•จ๋˜์–ด๋„ ์‹ค์ œ๋กœ๋Š” ํ•œ ๋ฒˆ๋งŒ ์ฒ˜๋ฆฌ๋ผ. ๋งŒ์•ฝ ์ธํด๋ฃจ๋“œ ๊ฐ€๋“œ๊ฐ€ ์—†๋‹ค๋ฉด ๊ตฌ์กฐ์ฒด๋‚˜ ํ•จ์ˆ˜๊ฐ€ ์ค‘๋ณต ์ •์˜๋˜์–ด ์ปดํŒŒ์ผ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฑฐ์•ผ! ๐Ÿ˜ฑ

๐Ÿ’ก ํ˜„๋Œ€์ ์ธ ๋ฐฉ๋ฒ•: ๋งŽ์€ ์ปดํŒŒ์ผ๋Ÿฌ๋“ค์ด #pragma once๋ฅผ ์ง€์›ํ•ด. ์ด๊ฑด ์ธํด๋ฃจ๋“œ ๊ฐ€๋“œ์™€ ๊ฐ™์€ ์—ญํ• ์„ ํ•˜์ง€๋งŒ ๋” ๊ฐ„๋‹จํ•˜๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์–ด!

#pragma once

ํ•˜์ง€๋งŒ ์ด๊ฑด ํ‘œ์ค€์ด ์•„๋‹ˆ๋ผ์„œ ๋ชจ๋“  ์ปดํŒŒ์ผ๋Ÿฌ์—์„œ ์ง€์›๋˜๋Š” ๊ฑด ์•„๋‹ˆ์•ผ. ์ด์‹์„ฑ์ด ์ค‘์š”ํ•˜๋‹ค๋ฉด ์ „ํ†ต์ ์ธ ์ธํด๋ฃจ๋“œ ๊ฐ€๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ์•ˆ์ „ํ•ด!

๐Ÿ”น #if, #elif, #else

๋” ๋ณต์žกํ•œ ์กฐ๊ฑด์„ ์ฒ˜๋ฆฌํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด #if ์ง€์‹œ์ž๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด. ์ด๊ฑด ์ผ๋ฐ˜์ ์ธ if๋ฌธ์ฒ˜๋Ÿผ ๋™์ž‘ํ•˜์ง€๋งŒ, ์ปดํŒŒ์ผ ํƒ€์ž„์— ํ‰๊ฐ€๋ผ!

#define PLATFORM_WINDOWS 1
#define PLATFORM_LINUX 2
#define PLATFORM_MAC 3

#define CURRENT_PLATFORM PLATFORM_LINUX

#if CURRENT_PLATFORM == PLATFORM_WINDOWS
    #include <windows.h>
    #define PATH_SEPARATOR '\\'
    #define LINE_ENDING "\r\n"
#elif CURRENT_PLATFORM == PLATFORM_LINUX
    #include <unistd.h>
    #define PATH_SEPARATOR '/'
    #define LINE_ENDING "\n"
#elif CURRENT_PLATFORM == PLATFORM_MAC
    #include <unistd.h>
    #define PATH_SEPARATOR '/'
    #define LINE_ENDING "\n"
#else
    #error "Unknown platform"
#endif

void print_path(const char* dir, const char* file) {
    printf("%s%c%s%s", dir, PATH_SEPARATOR, file, LINE_ENDING);
}

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํ”Œ๋žซํผ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ํ—ค๋” ํŒŒ์ผ์„ ํฌํ•จํ•˜๊ณ , ๋‹ค๋ฅธ ์ƒ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด. ํฌ๋กœ์Šค ํ”Œ๋žซํผ ๊ฐœ๋ฐœํ•  ๋•Œ ์ •๋ง ์œ ์šฉํ•˜์ง€! ๐ŸŒ

๐Ÿ”น #defined ์—ฐ์‚ฐ์ž

#if ์•ˆ์—์„œ ๋งคํฌ๋กœ๊ฐ€ ์ •์˜๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๋ ค๋ฉด defined ์—ฐ์‚ฐ์ž๋ฅผ ์‚ฌ์šฉํ•ด.

#if defined(DEBUG_MODE) && defined(VERBOSE_LOGGING)
    #define DETAILED_LOG(msg) printf("[DETAILED] %s\n", msg)
#else
    #define DETAILED_LOG(msg)
#endif

#if !defined(MAX_CONNECTIONS)
    #define MAX_CONNECTIONS 100
#endif

#if defined(USE_SSL) || defined(USE_TLS)
    #define SECURE_CONNECTION 1
#else
    #define SECURE_CONNECTION 0
#endif

defined๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋…ผ๋ฆฌ ์—ฐ์‚ฐ์ž(&&, ||, !)๋ฅผ ์กฐํ•ฉํ•ด์„œ ๋ณต์žกํ•œ ์กฐ๊ฑด์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด! ๐Ÿงฉ

๐ŸŽจ ๊ณ ๊ธ‰ ๋งคํฌ๋กœ ํ…Œํฌ๋‹‰

์ด์ œ ์ข€ ๋” ๊ณ ๊ธ‰ ๊ธฐ์ˆ ๋“ค์„ ์•Œ์•„๋ณผ๊นŒ? ์ด๋Ÿฐ ํ…Œํฌ๋‹‰๋“ค์„ ์ž˜ ํ™œ์šฉํ•˜๋ฉด ์ •๋ง ๊ฐ•๋ ฅํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์–ด! ๐Ÿ’ช

๐Ÿ”น ๋ฌธ์ž์—ดํ™” ์—ฐ์‚ฐ์ž (#)

# ์—ฐ์‚ฐ์ž๋ฅผ ๋งคํฌ๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜ ์•ž์— ๋ถ™์ด๋ฉด, ๊ทธ ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์–ด!

#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)

#define PRINT_VAR(var) printf(#var " = %d\n", var)
#define ASSERT(condition) \
    if (!(condition)) { \
        fprintf(stderr, "Assertion failed: %s, file %s, line %d\n", \
                #condition, __FILE__, __LINE__); \
        exit(1); \
    }

int main() {
    int age = 25;
    int score = 95;
    
    PRINT_VAR(age);      // "age = 25" ์ถœ๋ ฅ
    PRINT_VAR(score);    // "score = 95" ์ถœ๋ ฅ
    
    ASSERT(age > 0);
    ASSERT(score <= 100);
    
    printf("Version: " TOSTRING(VERSION_MAJOR) "." TOSTRING(VERSION_MINOR) "\n");
    
    return 0;
}

์ด ๊ธฐ๋Šฅ์€ ๋””๋ฒ„๊น…ํ•  ๋•Œ ํŠนํžˆ ์œ ์šฉํ•ด! ๋ณ€์ˆ˜ ์ด๋ฆ„๊ณผ ๊ฐ’์„ ํ•จ๊ป˜ ์ถœ๋ ฅํ•  ์ˆ˜ ์žˆ๊ฑฐ๋“ . ๐Ÿ”

๐Ÿ”น ํ† ํฐ ๊ฒฐํ•ฉ ์—ฐ์‚ฐ์ž (##)

## ์—ฐ์‚ฐ์ž๋Š” ๋‘ ๊ฐœ์˜ ํ† ํฐ์„ ํ•˜๋‚˜๋กœ ํ•ฉ์ณ์ค˜. ์ด๊ฑธ ์‚ฌ์šฉํ•˜๋ฉด ๋™์ ์œผ๋กœ ์‹๋ณ„์ž๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด!

#define CONCAT(a, b) a##b
#define MAKE_FUNCTION(type) \
    void print_##type(type value) { \
        printf("Value: %d\n", value); \
    }

// ์—ฌ๋Ÿฌ ํƒ€์ž…์— ๋Œ€ํ•œ ํ•จ์ˆ˜ ์ž๋™ ์ƒ์„ฑ
MAKE_FUNCTION(int)
MAKE_FUNCTION(long)

#define DECLARE_VARIABLE(type, name) type var_##name

int main() {
    DECLARE_VARIABLE(int, counter) = 0;    // int var_counter = 0;
    DECLARE_VARIABLE(double, price) = 99.99;  // double var_price = 99.99;
    
    print_int(42);
    print_long(1000000L);
    
    int xy = CONCAT(1, 23);  // int xy = 123;
    printf("xy = %d\n", xy);
    
    return 0;
}

ํ† ํฐ ๊ฒฐํ•ฉ์€ ์ œ๋„ค๋ฆญ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ํ‰๋‚ด๋‚ผ ๋•Œ ์ž์ฃผ ์‚ฌ์šฉ๋ผ. C++์˜ ํ…œํ”Œ๋ฆฟ์ฒ˜๋Ÿผ ๋ง์ด์•ผ! ๐ŸŽฏ

๐Ÿ”น ๊ฐ€๋ณ€ ์ธ์ž ๋งคํฌ๋กœ (...)

C99๋ถ€ํ„ฐ๋Š” ๋งคํฌ๋กœ์—์„œ๋„ ๊ฐ€๋ณ€ ์ธ์ž๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด! __VA_ARGS__๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋ผ.

#define LOG_INFO(fmt, ...) \
    printf("[INFO] " fmt "\n", ##__VA_ARGS__)

#define LOG_ERROR(fmt, ...) \
    fprintf(stderr, "[ERROR] %s:%d: " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__)

#define DEBUG_PRINTF(level, fmt, ...) \
    do { \
        if (DEBUG_LEVEL >= level) { \
            printf("[DEBUG-%d] " fmt "\n", level, ##__VA_ARGS__); \
        } \
    } while(0)

#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))

int main() {
    LOG_INFO("Program started");
    LOG_INFO("Processing %d items", 10);
    
    int numbers[] = {1, 2, 3, 4, 5};
    LOG_INFO("Array size: %zu", ARRAY_SIZE(numbers));
    
    int error_code = -1;
    if (error_code < 0) {
        LOG_ERROR("Invalid error code: %d", error_code);
    }
    
    return 0;
}

##__VA_ARGS__์—์„œ ##๋Š” GNU ํ™•์žฅ ๊ธฐ๋Šฅ์œผ๋กœ, ์ธ์ž๊ฐ€ ์—†์„ ๋•Œ ์•ž์˜ ์‰ผํ‘œ๋ฅผ ์ž๋™์œผ๋กœ ์ œ๊ฑฐํ•ด์ค˜. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ธ์ž ์—†์ด ๋งคํฌ๋กœ๋ฅผ ํ˜ธ์ถœํ•ด๋„ ์ปดํŒŒ์ผ ์—๋Ÿฌ๊ฐ€ ๋‚˜์ง€ ์•Š์•„! ๐Ÿ˜Š

๐Ÿ”น X-Macro ํŒจํ„ด

X-Macro๋Š” ์ •๋ง ๊ฐ•๋ ฅํ•œ ํŒจํ„ด์ด์•ผ! ๋ฐ์ดํ„ฐ์™€ ์ฝ”๋“œ๋ฅผ ํ•œ ๊ณณ์—์„œ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค˜. ์˜ˆ๋ฅผ ๋“ค์–ด, ์—ด๊ฑฐํ˜•๊ณผ ๋ฌธ์ž์—ด ๋ฐฐ์—ด์„ ๋™๊ธฐํ™”ํ•  ๋•Œ ์œ ์šฉํ•ด.

// colors.def ํŒŒ์ผ (๋˜๋Š” ๊ฐ™์€ ํŒŒ์ผ ๋‚ด)
#define COLOR_LIST \
    X(RED, "๋นจ๊ฐ•") \
    X(GREEN, "์ดˆ๋ก") \
    X(BLUE, "ํŒŒ๋ž‘") \
    X(YELLOW, "๋…ธ๋ž‘") \
    X(BLACK, "๊ฒ€์ •") \
    X(WHITE, "ํ•˜์–‘")

// ์—ด๊ฑฐํ˜• ์ƒ์„ฑ
#define X(name, str) COLOR_##name,
enum Color {
    COLOR_LIST
    COLOR_COUNT
};
#undef X

// ๋ฌธ์ž์—ด ๋ฐฐ์—ด ์ƒ์„ฑ
#define X(name, str) str,
const char* color_names[] = {
    COLOR_LIST
};
#undef X

// ํ•จ์ˆ˜ ์ƒ์„ฑ
#define X(name, str) \
    void set_##name##_color() { \
        printf("Setting color to %s\n", str); \
    }
COLOR_LIST
#undef X

int main() {
    enum Color my_color = COLOR_RED;
    printf("Color: %s\n", color_names[my_color]);
    
    set_RED_color();
    set_BLUE_color();
    
    // ๋ชจ๋“  ์ƒ‰์ƒ ์ถœ๋ ฅ
    for (int i = 0; i < COLOR_COUNT; i++) {
        printf("%d: %s\n", i, color_names[i]);
    }
    
    return 0;
}

X-Macro ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๋ฉด ์ƒ‰์ƒ์„ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•  ๋•Œ COLOR_LIST ํ•œ ๊ณณ๋งŒ ์ˆ˜์ •ํ•˜๋ฉด ๋ผ! ์—ด๊ฑฐํ˜•, ๋ฌธ์ž์—ด ๋ฐฐ์—ด, ํ•จ์ˆ˜๋“ค์ด ๋ชจ๋‘ ์ž๋™์œผ๋กœ ์—…๋ฐ์ดํŠธ๋˜์ง€. ์ •๋ง ํŽธ๋ฆฌํ•˜์ง€ ์•Š์•„? ๐ŸŽจ

๐Ÿ› ๏ธ ์‹ค์ „ ํ™œ์šฉ ์˜ˆ์ œ

์ด๋ก ์€ ์ถฉ๋ถ„ํžˆ ๋ฐฐ์› ์œผ๋‹ˆ, ์ด์ œ ์‹ค์ „์—์„œ ์–ด๋–ป๊ฒŒ ํ™œ์šฉํ•˜๋Š”์ง€ ์•Œ์•„๋ณด์ž! ์‹ค์ œ ํ”„๋กœ์ ํŠธ์—์„œ ์ž์ฃผ ์‚ฌ์šฉ๋˜๋Š” ํŒจํ„ด๋“ค์„ ์†Œ๊ฐœํ• ๊ฒŒ. ๐Ÿš€

๐Ÿ”น ๋””๋ฒ„๊ทธ ๋นŒ๋“œ์™€ ๋ฆด๋ฆฌ์ฆˆ ๋นŒ๋“œ ๋ถ„๋ฆฌ

// config.h
#ifndef CONFIG_H
#define CONFIG_H

// ์ปดํŒŒ์ผ ์‹œ -DDEBUG ํ”Œ๋ž˜๊ทธ๋กœ ๋””๋ฒ„๊ทธ ๋ชจ๋“œ ํ™œ์„ฑํ™”
#ifdef DEBUG
    #define DEBUG_MODE 1
    #define OPTIMIZATION_LEVEL 0
    #define ENABLE_LOGGING 1
    #define ENABLE_ASSERTIONS 1
#else
    #define DEBUG_MODE 0
    #define OPTIMIZATION_LEVEL 3
    #define ENABLE_LOGGING 0
    #define ENABLE_ASSERTIONS 0
#endif

#if ENABLE_LOGGING
    #define LOG(level, fmt, ...) \
        printf("[%s] %s:%d: " fmt "\n", level, __FILE__, __LINE__, ##__VA_ARGS__)
    #define LOG_DEBUG(fmt, ...) LOG("DEBUG", fmt, ##__VA_ARGS__)
    #define LOG_INFO(fmt, ...) LOG("INFO", fmt, ##__VA_ARGS__)
    #define LOG_WARN(fmt, ...) LOG("WARN", fmt, ##__VA_ARGS__)
    #define LOG_ERROR(fmt, ...) LOG("ERROR", fmt, ##__VA_ARGS__)
#else
    #define LOG_DEBUG(fmt, ...)
    #define LOG_INFO(fmt, ...)
    #define LOG_WARN(fmt, ...)
    #define LOG_ERROR(fmt, ...)
#endif

#if ENABLE_ASSERTIONS
    #define ASSERT(condition) \
        do { \
            if (!(condition)) { \
                fprintf(stderr, "Assertion failed: %s, %s:%d\n", \
                        #condition, __FILE__, __LINE__); \
                abort(); \
            } \
        } while(0)
#else
    #define ASSERT(condition) ((void)0)
#endif

#endif // CONFIG_H
// main.c
#include "config.h"

int divide(int a, int b) {
    ASSERT(b != 0);  // ๋””๋ฒ„๊ทธ ๋ชจ๋“œ์—์„œ๋งŒ ์ฒดํฌ
    
    LOG_DEBUG("Dividing %d by %d", a, b);
    return a / b;
}

int main() {
    LOG_INFO("Program started");
    
    int result = divide(10, 2);
    LOG_INFO("Result: %d", result);
    
    #if DEBUG_MODE
    printf("Running in DEBUG mode\n");
    printf("Optimization level: %d\n", OPTIMIZATION_LEVEL);
    #else
    printf("Running in RELEASE mode\n");
    #endif
    
    LOG_INFO("Program finished");
    return 0;
}

// ์ปดํŒŒ์ผ ๋ฐฉ๋ฒ•:
// ๋””๋ฒ„๊ทธ: gcc -DDEBUG main.c -o main_debug
// ๋ฆด๋ฆฌ์ฆˆ: gcc main.c -o main_release

๐Ÿ”น ํ”Œ๋žซํผ๋ณ„ ์ฝ”๋“œ ๊ด€๋ฆฌ

// platform.h
#ifndef PLATFORM_H
#define PLATFORM_H

// ํ”Œ๋žซํผ ์ž๋™ ๊ฐ์ง€
#if defined(_WIN32) || defined(_WIN64)
    #define PLATFORM_WINDOWS
    #define OS_NAME "Windows"
#elif defined(__linux__)
    #define PLATFORM_LINUX
    #define OS_NAME "Linux"
#elif defined(__APPLE__) && defined(__MACH__)
    #define PLATFORM_MAC
    #define OS_NAME "macOS"
#else
    #define PLATFORM_UNKNOWN
    #define OS_NAME "Unknown"
    #warning "Unknown platform detected"
#endif

// ํ”Œ๋žซํผ๋ณ„ ํ•จ์ˆ˜ ์„ ์–ธ
#ifdef PLATFORM_WINDOWS
    #include <windows.h>
    #define SLEEP(ms) Sleep(ms)
    #define CLEAR_SCREEN() system("cls")
    #define PATH_MAX MAX_PATH
#else
    #include <unistd.h>
    #define SLEEP(ms) usleep((ms) * 1000)
    #define CLEAR_SCREEN() system("clear")
    #ifndef PATH_MAX
        #define PATH_MAX 4096
    #endif
#endif

// ์ปดํŒŒ์ผ๋Ÿฌ ๊ฐ์ง€
#if defined(__GNUC__)
    #define COMPILER_GCC
    #define COMPILER_NAME "GCC"
    #define COMPILER_VERSION __VERSION__
#elif defined(_MSC_VER)
    #define COMPILER_MSVC
    #define COMPILER_NAME "MSVC"
    #define STRINGIFY(x) #x
    #define TOSTRING(x) STRINGIFY(x)
    #define COMPILER_VERSION TOSTRING(_MSC_VER)
#elif defined(__clang__)
    #define COMPILER_CLANG
    #define COMPILER_NAME "Clang"
    #define COMPILER_VERSION __clang_version__
#endif

void print_platform_info() {
    printf("Operating System: %s\n", OS_NAME);
    printf("Compiler: %s\n", COMPILER_NAME);
    printf("Compiler Version: %s\n", COMPILER_VERSION);
}

#endif // PLATFORM_H

๐Ÿ”น ๊ธฐ๋Šฅ ํ”Œ๋ž˜๊ทธ ๊ด€๋ฆฌ

// features.h
#ifndef FEATURES_H
#define FEATURES_H

// ๊ธฐ๋Šฅ ํ”Œ๋ž˜๊ทธ ์ •์˜
#define FEATURE_DATABASE 1
#define FEATURE_NETWORKING 1
#define FEATURE_GRAPHICS 0
#define FEATURE_AUDIO 0
#define FEATURE_ENCRYPTION 1

// ๊ธฐ๋Šฅ๋ณ„ ์กฐ๊ฑด๋ถ€ ์ปดํŒŒ์ผ
#if FEATURE_DATABASE
    #include "database.h"
    #define DB_CONNECT(host) db_connect(host)
    #define DB_QUERY(sql) db_query(sql)
#else
    #define DB_CONNECT(host) ((void)0)
    #define DB_QUERY(sql) ((void)0)
#endif

#if FEATURE_NETWORKING
    #include "network.h"
    #define NET_SEND(data) network_send(data)
    #define NET_RECEIVE() network_receive()
#else
    #define NET_SEND(data) ((void)0)
    #define NET_RECEIVE() NULL
#endif

#if FEATURE_ENCRYPTION
    #include "crypto.h"
    #define ENCRYPT(data) encrypt_data(data)
    #define DECRYPT(data) decrypt_data(data)
#else
    #define ENCRYPT(data) (data)
    #define DECRYPT(data) (data)
#endif

void print_enabled_features() {
    printf("Enabled features:\n");
    #if FEATURE_DATABASE
    printf("  - Database\n");
    #endif
    #if FEATURE_NETWORKING
    printf("  - Networking\n");
    #endif
    #if FEATURE_GRAPHICS
    printf("  - Graphics\n");
    #endif
    #if FEATURE_AUDIO
    printf("  - Audio\n");
    #endif
    #if FEATURE_ENCRYPTION
    printf("  - Encryption\n");
    #endif
}

#endif // FEATURES_H

์ด๋ ‡๊ฒŒ ๊ธฐ๋Šฅ ํ”Œ๋ž˜๊ทธ๋ฅผ ๊ด€๋ฆฌํ•˜๋ฉด ํ•„์š”ํ•œ ๊ธฐ๋Šฅ๋งŒ ์„ ํƒ์ ์œผ๋กœ ์ปดํŒŒ์ผํ•  ์ˆ˜ ์žˆ์–ด. ์ž„๋ฒ ๋””๋“œ ์‹œ์Šคํ…œ์ฒ˜๋Ÿผ ๋ฆฌ์†Œ์Šค๊ฐ€ ์ œํ•œ๋œ ํ™˜๊ฒฝ์—์„œ ํŠนํžˆ ์œ ์šฉํ•˜์ง€! ๐Ÿ’พ

๐ŸŽ“ ๋งคํฌ๋กœ ์‚ฌ์šฉ ์‹œ ์ฃผ์˜์‚ฌํ•ญ๊ณผ ๋ฒ ์ŠคํŠธ ํ”„๋ž™ํ‹ฐ์Šค

๋งคํฌ๋กœ๋Š” ๊ฐ•๋ ฅํ•˜์ง€๋งŒ, ์ž˜๋ชป ์‚ฌ์šฉํ•˜๋ฉด ๋””๋ฒ„๊น…ํ•˜๊ธฐ ์–ด๋ ค์šด ๋ฒ„๊ทธ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด. ์—ฌ๊ธฐ ๋ช‡ ๊ฐ€์ง€ ์ฃผ์˜์‚ฌํ•ญ๊ณผ ๋ฒ ์ŠคํŠธ ํ”„๋ž™ํ‹ฐ์Šค๋ฅผ ์•Œ๋ ค์ค„๊ฒŒ! โš ๏ธ

๐Ÿ”น ๋งคํฌ๋กœ์˜ ํ•จ์ •๋“ค

1. ๋ถ€์ž‘์šฉ(Side Effect) ๋ฌธ์ œ ๋งคํฌ๋กœ๋Š” ์ธ์ž๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ํ‰๊ฐ€ํ•  ์ˆ˜ ์žˆ์–ด!
// ์ž˜๋ชป๋œ ์˜ˆ
#define MAX(a, b) ((a) > (b) ? (a) : (b))

int x = 5;
int result = MAX(x++, 10);  // x๊ฐ€ ๋‘ ๋ฒˆ ์ฆ๊ฐ€ํ•  ์ˆ˜ ์žˆ์Œ!

// ๋” ์•ˆ์ „ํ•œ ๋ฐฉ๋ฒ• (C99 ์ด์ƒ)
#define MAX(a, b) ({ \
    __typeof__(a) _a = (a); \
    __typeof__(b) _b = (b); \
    _a > _b ? _a : _b; \
})

// ๋˜๋Š” inline ํ•จ์ˆ˜ ์‚ฌ์šฉ
static inline int max(int a, int b) {
    return a > b ? a : b;
}
2. ํƒ€์ž… ์•ˆ์ •์„ฑ ๋ถ€์กฑ ๋งคํฌ๋กœ๋Š” ํƒ€์ž… ์ฒดํฌ๋ฅผ ํ•˜์ง€ ์•Š์•„!
// ๋ฌธ์ œ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋Š” ์˜ˆ
#define SQUARE(x) ((x) * (x))

double d = 3.5;
int result = SQUARE(d);  // ๊ฒฝ๊ณ  ์—†์ด double์ด int๋กœ ๋ณ€ํ™˜๋จ

// ํ•ด๊ฒฐ์ฑ…: ํƒ€์ž…๋ณ„๋กœ ๋‹ค๋ฅธ ํ•จ์ˆ˜ ์‚ฌ์šฉ
static inline int square_int(int x) { return x * x; }
static inline double square_double(double x) { return x * x; }

// ๋˜๋Š” C11์˜ _Generic ์‚ฌ์šฉ
#define SQUARE(x) _Generic((x), \
    int: square_int, \
    double: square_double \
)(x)
3. ๋””๋ฒ„๊น…์˜ ์–ด๋ ค์›€ ๋งคํฌ๋กœ๋Š” ์ „์ฒ˜๋ฆฌ ๋‹จ๊ณ„์—์„œ ํ™•์žฅ๋˜๋ฏ€๋กœ ๋””๋ฒ„๊ฑฐ์—์„œ ์ถ”์ ํ•˜๊ธฐ ์–ด๋ ค์›Œ!
// ๋ณต์žกํ•œ ๋งคํฌ๋กœ๋Š” ๋””๋ฒ„๊น…์ด ์–ด๋ ค์›€
#define COMPLEX_CALC(a, b, c) \
    ((a) * (b) + (c) * ((a) - (b)) / ((c) + 1))

// ํ•ด๊ฒฐ์ฑ…: ์ค‘๊ฐ„ ๋‹จ๊ณ„๋ฅผ ๋ณ€์ˆ˜๋กœ ์ €์žฅ
#define COMPLEX_CALC_DEBUG(a, b, c) ({ \
    int _a = (a), _b = (b), _c = (c); \
    int _step1 = _a * _b; \
    int _step2 = _a - _b; \
    int _step3 = _c * _step2; \
    int _step4 = _c + 1; \
    _step1 + _step3 / _step4; \
})

๐Ÿ”น ๋ฒ ์ŠคํŠธ ํ”„๋ž™ํ‹ฐ์Šค

โœ… ๋งคํฌ๋กœ ์ž‘์„ฑ ๊ฐ€์ด๋“œ๋ผ์ธ

1. ๋งคํฌ๋กœ ์ด๋ฆ„์€ ๋Œ€๋ฌธ์ž๋กœ
#define MAX_SIZE 100 โœ…
#define maxSize 100 โŒ

2. ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ํ•ญ์ƒ ๊ด„ํ˜ธ๋กœ ๊ฐ์‹ธ๊ธฐ
#define SQUARE(x) ((x) * (x)) โœ…
#define SQUARE(x) x * x โŒ

3. ์ „์ฒด ํ‘œํ˜„์‹๋„ ๊ด„ํ˜ธ๋กœ ๊ฐ์‹ธ๊ธฐ
#define ADD(a, b) ((a) + (b)) โœ…
#define ADD(a, b) (a) + (b) โŒ

4. ๋‹ค์ค‘ ๋ฌธ์žฅ์€ do-while(0)๋กœ ๊ฐ์‹ธ๊ธฐ
#define SWAP(a,b) do { int t=a; a=b; b=t; } while(0)
โœ…
#define SWAP(a,b) { int t=a; a=b; b=t; } โŒ

5. ๊ฐ„๋‹จํ•œ ๊ฒฝ์šฐ inline ํ•จ์ˆ˜ ๊ณ ๋ ค
ํƒ€์ž… ์•ˆ์ •์„ฑ๊ณผ ๋””๋ฒ„๊น…์ด ์ค‘์š”ํ•˜๋ฉด ๋งคํฌ๋กœ ๋Œ€์‹  inline ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉ!

6. ๋งคํฌ๋กœ ์‚ฌ์šฉ ํ›„ #undef๋กœ ์ •๋ฆฌ
ํŠนํžˆ X-Macro ํŒจํ„ด์—์„œ๋Š” ํ•„์ˆ˜!
// ์ข‹์€ ๋งคํฌ๋กœ ์˜ˆ์ œ
#define SAFE_FREE(ptr) \
    do { \
        if ((ptr) != NULL) { \
            free(ptr); \
            (ptr) = NULL; \
        } \
    } while(0)

#define ARRAY_LENGTH(arr) \
    (sizeof(arr) / sizeof((arr)[0]))

#define UNUSED(x) ((void)(x))

#define LIKELY(x) __builtin_expect(!!(x), 1)
#define UNLIKELY(x) __builtin_expect(!!(x), 0)

// ์‚ฌ์šฉ ์˜ˆ
int main() {
    int* data = malloc(100 * sizeof(int));
    
    // ... ๋ฐ์ดํ„ฐ ์‚ฌ์šฉ ...
    
    SAFE_FREE(data);  // NULL ์ฒดํฌ์™€ ํฌ์ธํ„ฐ ์ดˆ๊ธฐํ™”๋ฅผ ์ž๋™์œผ๋กœ!
    
    int numbers[] = {1, 2, 3, 4, 5};
    for (size_t i = 0; i < ARRAY_LENGTH(numbers); i++) {
        printf("%d ", numbers[i]);
    }
    
    return 0;
}

๐ŸŒŸ ์ „์ฒ˜๋ฆฌ๊ธฐ์˜ ํŠน์ˆ˜ ๋งคํฌ๋กœ๋“ค

C ์–ธ์–ด๋Š” ๋ฏธ๋ฆฌ ์ •์˜๋œ ์œ ์šฉํ•œ ๋งคํฌ๋กœ๋“ค์„ ์ œ๊ณตํ•ด. ์ด๊ฒƒ๋“ค์„ ์ž˜ ํ™œ์šฉํ•˜๋ฉด ๋””๋ฒ„๊น…์ด๋‚˜ ๋กœ๊น…์— ์ •๋ง ์œ ์šฉํ•ด! ๐Ÿ”

๋งคํฌ๋กœ ์„ค๋ช… ์˜ˆ์‹œ ๊ฐ’
__FILE__ ํ˜„์žฌ ์†Œ์Šค ํŒŒ์ผ ์ด๋ฆ„ "main.c"
__LINE__ ํ˜„์žฌ ์ค„ ๋ฒˆํ˜ธ 42
__DATE__ ์ปดํŒŒ์ผ ๋‚ ์งœ "Dec 25 2024"
__TIME__ ์ปดํŒŒ์ผ ์‹œ๊ฐ„ "14:30:25"
__func__ ํ˜„์žฌ ํ•จ์ˆ˜ ์ด๋ฆ„ (C99) "main"
__STDC__ ํ‘œ์ค€ C ์ค€์ˆ˜ ์—ฌ๋ถ€ 1
__STDC_VERSION__ C ํ‘œ์ค€ ๋ฒ„์ „ 201112L (C11)
#include <stdio.h>

#define BUILD_INFO() \
    printf("Build Info:\n"); \
    printf("  File: %s\n", __FILE__); \
    printf("  Date: %s\n", __DATE__); \
    printf("  Time: %s\n", __TIME__); \
    printf("  C Standard: %ldL\n", __STDC_VERSION__)

#define TRACE() \
    printf("[TRACE] %s:%d in %s()\n", __FILE__, __LINE__, __func__)

#define LOG_FUNCTION_ENTRY() \
    printf(">>> Entering %s() at %s:%d\n", __func__, __FILE__, __LINE__)

#define LOG_FUNCTION_EXIT() \
    printf("<<< Exiting %s() at %s:%d\n", __func__, __FILE__, __LINE__)

void example_function() {
    LOG_FUNCTION_ENTRY();
    
    printf("Doing some work...\n");
    TRACE();
    
    LOG_FUNCTION_EXIT();
}

int main() {
    BUILD_INFO();
    printf("\n");
    
    example_function();
    
    return 0;
}

/* ์ถœ๋ ฅ ์˜ˆ:
Build Info:
  File: main.c
  Date: Dec 25 2024
  Time: 14:30:25
  C Standard: 201112L

>>> Entering example_function() at main.c:15
Doing some work...
[TRACE] main.c:18 in example_function()
<<< Exiting example_function() at main.c:20
*/

์ด๋Ÿฐ ํŠน์ˆ˜ ๋งคํฌ๋กœ๋“ค์€ ๋กœ๊น… ์‹œ์Šคํ…œ์„ ๋งŒ๋“ค ๋•Œ ์ •๋ง ์œ ์šฉํ•ด! ์–ด๋””์„œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋Š”์ง€ ์ •ํ™•ํžˆ ์ถ”์ ํ•  ์ˆ˜ ์žˆ๊ฑฐ๋“ . ๐ŸŽฏ

๐Ÿš€ ์‹ค๋ฌด์—์„œ์˜ ํ™œ์šฉ ์‚ฌ๋ก€

์ด์ œ ์‹ค์ œ ํ”„๋กœ์ ํŠธ์—์„œ ์–ด๋–ป๊ฒŒ ํ™œ์šฉ๋˜๋Š”์ง€ ๊ตฌ์ฒด์ ์ธ ์˜ˆ์ œ๋“ค์„ ์‚ดํŽด๋ณด์ž! ์ด๋Ÿฐ ํŒจํ„ด๋“ค์€ ์˜คํ”ˆ์†Œ์Šค ํ”„๋กœ์ ํŠธ์—์„œ๋„ ์ž์ฃผ ๋ณผ ์ˆ˜ ์žˆ์–ด. ๐ŸŒ

๐Ÿ”น ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋””๋ฒ„๊น… ๋„๊ตฌ

// memory_debug.h
#ifndef MEMORY_DEBUG_H
#define MEMORY_DEBUG_H

#include <stdlib.h>
#include <stdio.h>

#ifdef DEBUG_MEMORY

typedef struct {
    void* ptr;
    size_t size;
    const char* file;
    int line;
} MemoryAllocation;

#define MAX_ALLOCATIONS 10000
static MemoryAllocation allocations[MAX_ALLOCATIONS];
static int allocation_count = 0;

static void* debug_malloc(size_t size, const char* file, int line) {
    void* ptr = malloc(size);
    if (ptr && allocation_count < MAX_ALLOCATIONS) {
        allocations[allocation_count].ptr = ptr;
        allocations[allocation_count].size = size;
        allocations[allocation_count].file = file;
        allocations[allocation_count].line = line;
        allocation_count++;
        printf("[MALLOC] %zu bytes at %p (%s:%d)\n", size, ptr, file, line);
    }
    return ptr;
}

static void debug_free(void* ptr, const char* file, int line) {
    for (int i = 0; i < allocation_count; i++) {
        if (allocations[i].ptr == ptr) {
            printf("[FREE] %p (%s:%d) - originally allocated at %s:%d\n",
                   ptr, file, line, allocations[i].file, allocations[i].line);
            free(ptr);
            allocations[i] = allocations[--allocation_count];
            return;
        }
    }
    printf("[FREE] %p (%s:%d) - WARNING: not tracked!\n", ptr, file, line);
    free(ptr);
}

static void print_memory_leaks() {
    if (allocation_count > 0) {
        printf("\n=== MEMORY LEAKS DETECTED ===\n");
        for (int i = 0; i < allocation_count; i++) {
            printf("Leak: %zu bytes at %p (allocated at %s:%d)\n",
                   allocations[i].size, allocations[i].ptr,
                   allocations[i].file, allocations[i].line);
        }
        printf("Total leaks: %d allocations\n", allocation_count);
    } else {
        printf("\n=== NO MEMORY LEAKS ===\n");
    }
}

#define malloc(size) debug_malloc(size, __FILE__, __LINE__)
#define free(ptr) debug_free(ptr, __FILE__, __LINE__)
#define CHECK_LEAKS() print_memory_leaks()

#else

#define CHECK_LEAKS() ((void)0)

#endif // DEBUG_MEMORY

#endif // MEMORY_DEBUG_H
// ์‚ฌ์šฉ ์˜ˆ
#define DEBUG_MEMORY
#include "memory_debug.h"

int main() {
    int* array1 = malloc(10 * sizeof(int));
    int* array2 = malloc(20 * sizeof(int));
    
    // array1 ์‚ฌ์šฉ
    for (int i = 0; i < 10; i++) {
        array1[i] = i;
    }
    
    free(array1);
    // array2๋Š” ํ•ด์ œํ•˜์ง€ ์•Š์Œ (์˜๋„์ ์ธ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜)
    
    CHECK_LEAKS();  // ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜ ๋ณด๊ณ ์„œ ์ถœ๋ ฅ
    return 0;
}

๐Ÿ”น ์„ฑ๋Šฅ ์ธก์ • ๋งคํฌ๋กœ

// performance.h
#ifndef PERFORMANCE_H
#define PERFORMANCE_H

#include <time.h>
#include <stdio.h>

#ifdef ENABLE_PROFILING

#define PROFILE_START(name) \
    clock_t _profile_start_##name = clock(); \
    printf("[PROFILE] Starting: %s\n", #name)

#define PROFILE_END(name) \
    do { \
        clock_t _profile_end_##name = clock(); \
        double _profile_time_##name = \
            ((double)(_profile_end_##name - _profile_start_##name)) / CLOCKS_PER_SEC; \
        printf("[PROFILE] %s took %.6f seconds\n", #name, _profile_time_##name); \
    } while(0)

#define PROFILE_FUNCTION() \
    clock_t _func_start = clock(); \
    printf("[PROFILE] Entering function: %s\n", __func__); \
    void _profile_cleanup() { \
        clock_t _func_end = clock(); \
        double _func_time = ((double)(_func_end - _func_start)) / CLOCKS_PER_SEC; \
        printf("[PROFILE] %s took %.6f seconds\n", __func__, _func_time); \
    } \
    __attribute__((cleanup(_profile_cleanup))) int _dummy = 0; \
    (void)_dummy

#else

#define PROFILE_START(name) ((void)0)
#define PROFILE_END(name) ((void)0)
#define PROFILE_FUNCTION() ((void)0)

#endif // ENABLE_PROFILING

#endif // PERFORMANCE_H
// ์‚ฌ์šฉ ์˜ˆ
#define ENABLE_PROFILING
#include "performance.h"

void slow_function() {
    PROFILE_FUNCTION();
    
    // ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆฌ๋Š” ์ž‘์—… ์‹œ๋ฎฌ๋ ˆ์ด์…˜
    for (volatile int i = 0; i < 100000000; i++);
}

int main() {
    PROFILE_START(main_execution);
    
    PROFILE_START(initialization);
    // ์ดˆ๊ธฐํ™” ์ฝ”๋“œ
    for (volatile int i = 0; i < 50000000; i++);
    PROFILE_END(initialization);
    
    slow_function();
    
    PROFILE_START(cleanup);
    // ์ •๋ฆฌ ์ฝ”๋“œ
    for (volatile int i = 0; i < 30000000; i++);
    PROFILE_END(cleanup);
    
    PROFILE_END(main_execution);
    return 0;
}

๐Ÿ”น ๋‹จ์œ„ ํ…Œ์ŠคํŠธ ํ”„๋ ˆ์ž„์›Œํฌ

// test_framework.h
#ifndef TEST_FRAMEWORK_H
#define TEST_FRAMEWORK_H

#include <stdio.h>
#include <string.h>

static int _test_count = 0;
static int _test_passed = 0;
static int _test_failed = 0;

#define TEST_SUITE(name) \
    printf("\n=== Test Suite: %s ===\n", name)

#define TEST_CASE(name) \
    printf("\nTest: %s\n", name); \
    _test_count++

#define ASSERT_TRUE(condition) \
    do { \
        if (condition) { \
            printf("  โœ“ PASS: %s\n", #condition); \
            _test_passed++; \
        } else { \
            printf("  โœ— FAIL: %s (at %s:%d)\n", #condition, __FILE__, __LINE__); \
            _test_failed++; \
        } \
    } while(0)

#define ASSERT_FALSE(condition) ASSERT_TRUE(!(condition))

#define ASSERT_EQUAL(a, b) \
    do { \
        if ((a) == (b)) { \
            printf("  โœ“ PASS: %s == %s\n", #a, #b); \
            _test_passed++; \
        } else { \
            printf("  โœ— FAIL: %s != %s (at %s:%d)\n", #a, #b, __FILE__, __LINE__); \
            printf("    Expected: %d, Got: %d\n", (int)(b), (int)(a)); \
            _test_failed++; \
        } \
    } while(0)

#define ASSERT_STRING_EQUAL(a, b) \
    do { \
        if (strcmp(a, b) == 0) { \
            printf("  โœ“ PASS: %s == %s\n", #a, #b); \
            _test_passed++; \
        } else { \
            printf("  โœ— FAIL: %s != %s (at %s:%d)\n", #a, #b, __FILE__, __LINE__); \
            printf("    Expected: \"%s\", Got: \"%s\"\n", b, a); \
            _test_failed++; \
        } \
    } while(0)

#define TEST_SUMMARY() \
    do { \
        printf("\n=== Test Summary ===\n"); \
        printf("Total tests: %d\n", _test_count); \
        printf("Assertions: %d\n", _test_passed + _test_failed); \
        printf("Passed: %d\n", _test_passed); \
        printf("Failed: %d\n", _test_failed); \
        if (_test_failed == 0) { \
            printf("Result: โœ“ ALL TESTS PASSED\n"); \
        } else { \
            printf("Result: โœ— SOME TESTS FAILED\n"); \
        } \
    } while(0)

#endif // TEST_FRAMEWORK_H
// ์‚ฌ์šฉ ์˜ˆ
#include "test_framework.h"

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

int multiply(int a, int b) {
    return a * b;
}

const char* get_greeting() {
    return "Hello, World!";
}

int main() {
    TEST_SUITE("Math Functions");
    
    TEST_CASE("Addition");
    ASSERT_EQUAL(add(2, 3), 5);
    ASSERT_EQUAL(add(-1, 1), 0);
    ASSERT_EQUAL(add(0, 0), 0);
    
    TEST_CASE("Multiplication");
    ASSERT_EQUAL(multiply(2, 3), 6);
    ASSERT_EQUAL(multiply(-2, 3), -6);
    ASSERT_EQUAL(multiply(0, 100), 0);
    
    TEST_SUITE("String Functions");
    
    TEST_CASE("Greeting");
    ASSERT_STRING_EQUAL(get_greeting(), "Hello, World!");
    ASSERT_TRUE(strlen(get_greeting()) > 0);
    
    TEST_SUMMARY();
    
    return _test_failed > 0 ? 1 : 0;
}

์ด๋Ÿฐ ์‹์œผ๋กœ ์ „์ฒ˜๋ฆฌ๊ธฐ๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๊ฐ„๋‹จํ•œ ํ…Œ์ŠคํŠธ ํ”„๋ ˆ์ž„์›Œํฌ๋„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด! ๋ฌผ๋ก  ์‹ค์ œ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” CUnit์ด๋‚˜ Check ๊ฐ™์€ ์ „๋ฌธ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ์ข‹์ง€๋งŒ, ์›๋ฆฌ๋ฅผ ์ดํ•ดํ•˜๋Š” ๋ฐ๋Š” ์ด๋Ÿฐ ์˜ˆ์ œ๊ฐ€ ๋„์›€์ด ๋˜์ง€! ๐Ÿงช

๐ŸŽจ ์žฌ๋Šฅ๋„ท์—์„œ ๋ฐฐ์šฐ๋Š” C ํ”„๋กœ๊ทธ๋ž˜๋ฐ

์—ฌ๊ธฐ๊นŒ์ง€ C์–ธ์–ด์˜ ์ „์ฒ˜๋ฆฌ๊ธฐ์™€ ๋งคํฌ๋กœ์— ๋Œ€ํ•ด ๊นŠ์ด ์žˆ๊ฒŒ ์•Œ์•„๋ดค์–ด! ์ด๋Ÿฐ ๊ณ ๊ธ‰ ๊ธฐ์ˆ ๋“ค์„ ํ˜ผ์ž ๊ณต๋ถ€ํ•˜๊ธฐ ์–ด๋ ต๋‹ค๋ฉด, ์žฌ๋Šฅ๋„ท์—์„œ ์ „๋ฌธ๊ฐ€์˜ ๋„์›€์„ ๋ฐ›์•„๋ณด๋Š” ๊ฒƒ๋„ ์ข‹์€ ๋ฐฉ๋ฒ•์ด์•ผ. ์žฌ๋Šฅ๋„ท์€ ๋‹ค์–‘ํ•œ ๋ถ„์•ผ์˜ ์ „๋ฌธ๊ฐ€๋“ค์ด ์ž์‹ ์˜ ์ง€์‹๊ณผ ๊ฒฝํ—˜์„ ๊ณต์œ ํ•˜๋Š” ํ”Œ๋žซํผ์ด๊ฑฐ๋“ ! ๐Ÿ’ก

ํŠนํžˆ C์–ธ์–ด ๊ฐ™์€ ์ €์ˆ˜์ค€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ์‹ค๋ฌด ๊ฒฝํ—˜์ด ํ’๋ถ€ํ•œ ๊ฐœ๋ฐœ์ž์—๊ฒŒ ๋ฐฐ์šฐ๋ฉด ํ›จ์”ฌ ๋น ๋ฅด๊ฒŒ ์„ฑ์žฅํ•  ์ˆ˜ ์žˆ์–ด. ์ฝ”๋“œ ๋ฆฌ๋ทฐ๋ฅผ ๋ฐ›๊ฑฐ๋‚˜, ์‹ค์ „ ํ”„๋กœ์ ํŠธ ๊ฒฝํ—˜์„ ์Œ“๊ฑฐ๋‚˜, ํŠน์ • ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์šฐ๊ณ  ์‹ถ๋‹ค๋ฉด ์žฌ๋Šฅ๋„ท์˜ '์ง€์‹์ธ์˜ ์ˆฒ'์„ ํ™œ์šฉํ•ด๋ณด๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•ด! ๐ŸŒณ

๐ŸŽฏ ์ „์ฒ˜๋ฆฌ๊ธฐ ๋งˆ์Šคํ„ฐ๋ฅผ ์œ„ํ•œ ํ•™์Šต ๋กœ๋“œ๋งต 1๋‹จ๊ณ„: ๊ธฐ๋ณธ ๋งคํฌ๋กœ์™€ #include ์ดํ•ดํ•˜๊ธฐ
2๋‹จ๊ณ„: ์กฐ๊ฑด๋ถ€ ์ปดํŒŒ์ผ๋กœ ํ”Œ๋žซํผ๋ณ„ ์ฝ”๋“œ ์ž‘์„ฑํ•˜๊ธฐ
3๋‹จ๊ณ„: ํ•จ์ˆ˜ํ˜• ๋งคํฌ๋กœ์™€ ๊ณ ๊ธ‰ ์—ฐ์‚ฐ์ž ํ™œ์šฉํ•˜๊ธฐ
4๋‹จ๊ณ„: X-Macro ํŒจํ„ด ๊ฐ™์€ ๊ณ ๊ธ‰ ํ…Œํฌ๋‹‰ ์ตํžˆ๊ธฐ
5๋‹จ๊ณ„: ์‹ค์ „ ํ”„๋กœ์ ํŠธ์— ์ ์šฉํ•˜๊ณ  ์ตœ์ ํ™”ํ•˜๊ธฐ

๐Ÿ” ์ „์ฒ˜๋ฆฌ๊ธฐ ๋””๋ฒ„๊น… ํŒ

์ „์ฒ˜๋ฆฌ๊ธฐ ์ฝ”๋“œ๋ฅผ ๋””๋ฒ„๊น…ํ•˜๋Š” ๊ฑด ์ผ๋ฐ˜ ์ฝ”๋“œ๋ณด๋‹ค ๊นŒ๋‹ค๋กœ์šธ ์ˆ˜ ์žˆ์–ด. ํ•˜์ง€๋งŒ ๋ช‡ ๊ฐ€์ง€ ์œ ์šฉํ•œ ํŒ๋“ค์ด ์žˆ์ง€! ๐Ÿ”ง

๐Ÿ”น ์ „์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ ํ™•์ธํ•˜๊ธฐ

์ปดํŒŒ์ผ๋Ÿฌ์˜ ์ „์ฒ˜๋ฆฌ ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ๋งคํฌ๋กœ๊ฐ€ ์–ด๋–ป๊ฒŒ ํ™•์žฅ๋˜๋Š”์ง€ ์ง์ ‘ ๋ณผ ์ˆ˜ ์žˆ์–ด!

// GCC/Clang
gcc -E source.c -o preprocessed.c

// MSVC
cl /E source.c > preprocessed.c

// ํŠน์ • ๋งคํฌ๋กœ๋งŒ ํ™•์ธ
gcc -E -dM source.c | grep "MACRO_NAME"

-E ์˜ต์…˜์„ ์‚ฌ์šฉํ•˜๋ฉด ์ „์ฒ˜๋ฆฌ๋งŒ ์ˆ˜ํ–‰ํ•˜๊ณ  ์ปดํŒŒ์ผ์€ ํ•˜์ง€ ์•Š์•„. ๊ฒฐ๊ณผ ํŒŒ์ผ์„ ์—ด์–ด๋ณด๋ฉด ๋ชจ๋“  ๋งคํฌ๋กœ๊ฐ€ ํ™•์žฅ๋œ ์ƒํƒœ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์ง€! ๐Ÿ‘€

๐Ÿ”น #error์™€ #warning ํ™œ์šฉ

// ์ปดํŒŒ์ผ ํƒ€์ž„ ์ฒดํฌ
#ifndef REQUIRED_MACRO
    #error "REQUIRED_MACRO must be defined!"
#endif

#if MAX_SIZE < 100
    #error "MAX_SIZE must be at least 100"
#endif

// ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€
#ifdef DEPRECATED_FEATURE
    #warning "DEPRECATED_FEATURE is deprecated and will be removed in v2.0"
#endif

// ํ”Œ๋žซํผ ์ฒดํฌ
#if !defined(PLATFORM_WINDOWS) && !defined(PLATFORM_LINUX) && !defined(PLATFORM_MAC)
    #error "Unsupported platform! Please define PLATFORM_WINDOWS, PLATFORM_LINUX, or PLATFORM_MAC"
#endif

#error๋Š” ์ปดํŒŒ์ผ์„ ์ค‘๋‹จ์‹œํ‚ค๊ณ , #warning์€ ๊ฒฝ๊ณ ๋งŒ ํ‘œ์‹œํ•ด. ์ด๊ฑธ ํ™œ์šฉํ•˜๋ฉด ์ž˜๋ชป๋œ ์„ค์ •์œผ๋กœ ์ปดํŒŒ์ผํ•˜๋Š” ๊ฑธ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์–ด! ๐Ÿšซ

๐Ÿ”น ๋งคํฌ๋กœ ๋””๋ฒ„๊น… ํ—ฌํผ

// ๋งคํฌ๋กœ ๊ฐ’ ์ถœ๋ ฅ
#define PRINT_MACRO(x) printf(#x " = %s\n", STRINGIFY(x))
#define STRINGIFY(x) #x

// ๋งคํฌ๋กœ ์ •์˜ ์—ฌ๋ถ€ ํ™•์ธ
#define IS_DEFINED(macro) \
    printf(#macro " is %s\n", \
           STRINGIFY(macro)[0] == '1' ? "defined" : "not defined")

int main() {
    #ifdef DEBUG
    PRINT_MACRO(DEBUG);
    #endif
    
    PRINT_MACRO(MAX_SIZE);
    PRINT_MACRO(__FILE__);
    PRINT_MACRO(__LINE__);
    
    return 0;
}

๐Ÿ“š ์‹ค์ „ ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ ์˜ˆ์ œ

๋งˆ์ง€๋ง‰์œผ๋กœ, ์‹ค์ œ ํ”„๋กœ์ ํŠธ์—์„œ ์ „์ฒ˜๋ฆฌ๊ธฐ๋ฅผ ์–ด๋–ป๊ฒŒ ๊ตฌ์กฐํ™”ํ•˜๋Š”์ง€ ๋ณด์—ฌ์ค„๊ฒŒ! ์ด๊ฑด ์ค‘๋Œ€ํ˜• ํ”„๋กœ์ ํŠธ์—์„œ ์ž์ฃผ ์‚ฌ์šฉ๋˜๋Š” ํŒจํ„ด์ด์•ผ. ๐Ÿ—๏ธ

// config.h - ํ”„๋กœ์ ํŠธ ์ „์—ญ ์„ค์ •
#ifndef CONFIG_H
#define CONFIG_H

// ๋ฒ„์ „ ์ •๋ณด
#define VERSION_MAJOR 1
#define VERSION_MINOR 2
#define VERSION_PATCH 3
#define VERSION_STRING "1.2.3"

// ๋นŒ๋“œ ์„ค์ •
#ifdef RELEASE_BUILD
    #define DEBUG_MODE 0
    #define OPTIMIZATION_LEVEL 3
    #define ENABLE_LOGGING 0
#else
    #define DEBUG_MODE 1
    #define OPTIMIZATION_LEVEL 0
    #define ENABLE_LOGGING 1
#endif

// ํ”Œ๋žซํผ ์„ค์ •
#include "platform.h"

// ๊ธฐ๋Šฅ ํ”Œ๋ž˜๊ทธ
#include "features.h"

// ์ „์—ญ ์ƒ์ˆ˜
#define MAX_BUFFER_SIZE 4096
#define MAX_CONNECTIONS 100
#define TIMEOUT_SECONDS 30

#endif // CONFIG_H
// platform.h - ํ”Œ๋žซํผ๋ณ„ ์„ค์ •
#ifndef PLATFORM_H
#define PLATFORM_H

// ํ”Œ๋žซํผ ์ž๋™ ๊ฐ์ง€
#if defined(_WIN32) || defined(_WIN64)
    #define PLATFORM_WINDOWS 1
    #define PLATFORM_LINUX 0
    #define PLATFORM_MAC 0
#elif defined(__linux__)
    #define PLATFORM_WINDOWS 0
    #define PLATFORM_LINUX 1
    #define PLATFORM_MAC 0
#elif defined(__APPLE__)
    #define PLATFORM_WINDOWS 0
    #define PLATFORM_LINUX 0
    #define PLATFORM_MAC 1
#endif

// ํ”Œ๋žซํผ๋ณ„ ํ—ค๋”
#if PLATFORM_WINDOWS
    #include <windows.h>
    #define EXPORT __declspec(dllexport)
    #define IMPORT __declspec(dllimport)
#else
    #define EXPORT __attribute__((visibility("default")))
    #define IMPORT
#endif

// ํ”Œ๋žซํผ๋ณ„ ํ•จ์ˆ˜
#if PLATFORM_WINDOWS
    #define SLEEP_MS(ms) Sleep(ms)
#else
    #define SLEEP_MS(ms) usleep((ms) * 1000)
#endif

#endif // PLATFORM_H
// features.h - ๊ธฐ๋Šฅ ํ”Œ๋ž˜๊ทธ
#ifndef FEATURES_H
#define FEATURES_H

// ๊ธฐ๋Šฅ ํ™œ์„ฑํ™”/๋น„ํ™œ์„ฑํ™”
#define FEATURE_NETWORKING 1
#define FEATURE_DATABASE 1
#define FEATURE_ENCRYPTION 1
#define FEATURE_COMPRESSION 0
#define FEATURE_GUI 0

// ๊ธฐ๋Šฅ๋ณ„ ์„ค์ •
#if FEATURE_NETWORKING
    #define MAX_NETWORK_THREADS 10
    #define NETWORK_BUFFER_SIZE 8192
#endif

#if FEATURE_DATABASE
    #define DB_CONNECTION_POOL_SIZE 20
    #define DB_QUERY_TIMEOUT 5000
#endif

#endif // FEATURES_H
// logger.h - ๋กœ๊น… ์‹œ์Šคํ…œ
#ifndef LOGGER_H
#define LOGGER_H

#include "config.h"
#include <stdio.h>

#if ENABLE_LOGGING

typedef enum {
    LOG_LEVEL_DEBUG,
    LOG_LEVEL_INFO,
    LOG_LEVEL_WARN,
    LOG_LEVEL_ERROR
} LogLevel;

#define LOG(level, fmt, ...) \
    log_message(level, __FILE__, __LINE__, __func__, fmt, ##__VA_ARGS__)

#define LOG_DEBUG(fmt, ...) LOG(LOG_LEVEL_DEBUG, fmt, ##__VA_ARGS__)
#define LOG_INFO(fmt, ...) LOG(LOG_LEVEL_INFO, fmt, ##__VA_ARGS__)
#define LOG_WARN(fmt, ...) LOG(LOG_LEVEL_WARN, fmt, ##__VA_ARGS__)
#define LOG_ERROR(fmt, ...) LOG(LOG_LEVEL_ERROR, fmt, ##__VA_ARGS__)

void log_message(LogLevel level, const char* file, int line,
                const char* func, const char* fmt, ...);

#else

#define LOG_DEBUG(fmt, ...) ((void)0)
#define LOG_INFO(fmt, ...) ((void)0)
#define LOG_WARN(fmt, ...) ((void)0)
#define LOG_ERROR(fmt, ...) ((void)0)

#endif // ENABLE_LOGGING

#endif // LOGGER_H
// main.c - ๋ฉ”์ธ ํ”„๋กœ๊ทธ๋žจ
#include "config.h"
#include "logger.h"

int main() {
    LOG_INFO("Application started");
    LOG_INFO("Version: %s", VERSION_STRING);
    
    #if PLATFORM_WINDOWS
    LOG_INFO("Platform: Windows");
    #elif PLATFORM_LINUX
    LOG_INFO("Platform: Linux");
    #elif PLATFORM_MAC
    LOG_INFO("Platform: macOS");
    #endif
    
    #if DEBUG_MODE
    LOG_DEBUG("Running in DEBUG mode");
    #else
    LOG_INFO("Running in RELEASE mode");
    #endif
    
    LOG_INFO("Enabled features:");
    #if FEATURE_NETWORKING
    LOG_INFO("  - Networking");
    #endif
    #if FEATURE_DATABASE
    LOG_INFO("  - Database");
    #endif
    #if FEATURE_ENCRYPTION
    LOG_INFO("  - Encryption");
    #endif
    
    // ์‹ค์ œ ํ”„๋กœ๊ทธ๋žจ ๋กœ์ง...
    
    LOG_INFO("Application finished");
    return 0;
}

// ์ปดํŒŒ์ผ ์˜ˆ:
// ๋””๋ฒ„๊ทธ: gcc -DDEBUG main.c logger.c -o app_debug
// ๋ฆด๋ฆฌ์ฆˆ: gcc -DRELEASE_BUILD main.c logger.c -o app_release -O3

์ด๋Ÿฐ ์‹์œผ๋กœ ๊ตฌ์กฐํ™”ํ•˜๋ฉด ํ”„๋กœ์ ํŠธ๊ฐ€ ์ปค์ ธ๋„ ๊ด€๋ฆฌํ•˜๊ธฐ ์‰ฌ์›Œ์ ธ! ๊ฐ ์„ค์ •์ด ๋ช…ํ™•ํ•˜๊ฒŒ ๋ถ„๋ฆฌ๋˜์–ด ์žˆ๊ณ , ํ•„์š”์— ๋”ฐ๋ผ ์‰ฝ๊ฒŒ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๊ฑฐ๋“ . ๐ŸŽฏ

๐ŸŽ“ ๋งˆ๋ฌด๋ฆฌํ•˜๋ฉฐ

์™€! ์—ฌ๊ธฐ๊นŒ์ง€ ์ •๋ง ๊ธด ์—ฌ์ •์ด์—ˆ์ง€? ๐Ÿ˜… C์–ธ์–ด์˜ ์ „์ฒ˜๋ฆฌ๊ธฐ์™€ ๋งคํฌ๋กœ๋Š” ์ฒ˜์Œ์—๋Š” ๋‹จ์ˆœํ•ด ๋ณด์ด์ง€๋งŒ, ๊นŠ์ด ํŒŒ๊ณ ๋“ค๋ฉด ์ •๋ง ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ๋ผ๋Š” ๊ฑธ ์•Œ ์ˆ˜ ์žˆ์–ด. ์กฐ๊ฑด๋ถ€ ์ปดํŒŒ์ผ์„ ํ†ตํ•ด ํ”Œ๋žซํผ๋ณ„ ์ฝ”๋“œ๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ , ๋งคํฌ๋กœ๋กœ ๋ฐ˜๋ณต์ ์ธ ์ฝ”๋“œ๋ฅผ ์ค„์ด๊ณ , ๋””๋ฒ„๊ทธ ์ฝ”๋“œ๋ฅผ ์‰ฝ๊ฒŒ ๋„ฃ์—ˆ๋‹ค ๋บ๋‹ค ํ•  ์ˆ˜ ์žˆ์ง€! ๐Ÿš€

๐ŸŽฏ ํ•ต์‹ฌ ์š”์•ฝ 1. ์ „์ฒ˜๋ฆฌ๊ธฐ๋Š” ์ปดํŒŒ์ผ ์ „์— ํ…์ŠคํŠธ ์ˆ˜์ค€์—์„œ ์ฝ”๋“œ๋ฅผ ๋ณ€ํ™˜
2. #define์œผ๋กœ ์ƒ์ˆ˜์™€ ํ•จ์ˆ˜ํ˜• ๋งคํฌ๋กœ๋ฅผ ์ •์˜
3. ์กฐ๊ฑด๋ถ€ ์ปดํŒŒ์ผ๋กœ ํ”Œ๋žซํผ/๊ธฐ๋Šฅ๋ณ„ ์ฝ”๋“œ ๊ด€๋ฆฌ
4. ๋งคํฌ๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” ํ•ญ์ƒ ๊ด„ํ˜ธ๋กœ ๊ฐ์‹ธ๊ธฐ
5. ํŠน์ˆ˜ ๋งคํฌ๋กœ(__FILE__, __LINE__ ๋“ฑ)๋กœ ๋””๋ฒ„๊น… ๊ฐ•ํ™”
6. ๋ณต์žกํ•œ ๊ฒฝ์šฐ inline ํ•จ์ˆ˜ ๊ณ ๋ ค
7. ์ „์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•˜๋ฉฐ ๋””๋ฒ„๊น…

์ „์ฒ˜๋ฆฌ๊ธฐ๋ฅผ ์ž˜ ํ™œ์šฉํ•˜๋ฉด ์ฝ”๋“œ์˜ ์œ ์ง€๋ณด์ˆ˜์„ฑ๊ณผ ์ด์‹์„ฑ์ด ํฌ๊ฒŒ ํ–ฅ์ƒ๋ผ. ํ•˜์ง€๋งŒ ๊ณผ๋„ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๋ฉด ์ฝ”๋“œ๊ฐ€ ์ฝ๊ธฐ ์–ด๋ ค์›Œ์งˆ ์ˆ˜ ์žˆ์œผ๋‹ˆ, ์ ์ ˆํ•œ ๊ท ํ˜•์„ ์ฐพ๋Š” ๊ฒŒ ์ค‘์š”ํ•ด! ๊ฐ„๋‹จํ•œ ๊ฒฝ์šฐ์—๋Š” const ๋ณ€์ˆ˜๋‚˜ inline ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , ์ •๋ง ํ•„์š”ํ•œ ๊ฒฝ์šฐ์—๋งŒ ๋งคํฌ๋กœ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ์ข‹์•„. ๐ŸŽจ

C ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ์ €์ˆ˜์ค€ ์ œ์–ด๊ฐ€ ๊ฐ€๋Šฅํ•œ ๋งŒํผ ์ฑ…์ž„๋„ ํฌ์ง€. ์ „์ฒ˜๋ฆฌ๊ธฐ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€์•ผ. ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ์ธ ๋งŒํผ ์‹ ์ค‘ํ•˜๊ฒŒ ์‚ฌ์šฉํ•ด์•ผ ํ•ด. ํ•˜์ง€๋งŒ ์ œ๋Œ€๋กœ ์ดํ•ดํ•˜๊ณ  ํ™œ์šฉํ•˜๋ฉด, ์ •๋ง ์šฐ์•„ํ•˜๊ณ  ํšจ์œจ์ ์ธ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์–ด! ๐Ÿ’ช

์ด ๊ธ€์ด ์ „์ฒ˜๋ฆฌ๊ธฐ์™€ ๋งคํฌ๋กœ๋ฅผ ์ดํ•ดํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜์—ˆ๊ธธ ๋ฐ”๋ผ! ๊ถ๊ธˆํ•œ ์ ์ด ์žˆ๊ฑฐ๋‚˜ ๋” ๊นŠ์ด ๋ฐฐ์šฐ๊ณ  ์‹ถ๋‹ค๋ฉด, ์‹ค์ œ๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ณด๋ฉด์„œ ์‹คํ—˜ํ•ด๋ณด๋Š” ๊ฒŒ ๊ฐ€์žฅ ์ข‹์€ ํ•™์Šต ๋ฐฉ๋ฒ•์ด์•ผ. ๊ทธ๋ฆฌ๊ณ  ๋ง‰ํžˆ๋Š” ๋ถ€๋ถ„์ด ์žˆ๋‹ค๋ฉด ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์—์„œ ์ „๋ฌธ๊ฐ€์˜ ๋„์›€์„ ๋ฐ›๋Š” ๊ฒƒ๋„ ์ข‹์€ ๋ฐฉ๋ฒ•์ด๊ณ ! ๐ŸŒŸ

Happy Coding! ์ฆ๊ฑฐ์šด ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋˜๊ธธ ๋ฐ”๋ž„๊ฒŒ! ๐ŸŽ‰

๋Œ“๊ธ€ ์ž‘์„ฑ

์ด ๊ธ€์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ๋ถ„์˜ ์ƒ๊ฐ์„ ๋“ค๋ ค์ฃผ์„ธ์š”

๋Œ“๊ธ€ 0
๋Œ“๊ธ€์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘์ž…๋‹ˆ๋‹ค.

์•„์ง ๋Œ“๊ธ€์ด ์—†์Šต๋‹ˆ๋‹ค.