ν‹°μŠ€ν† λ¦¬ λ·°

728x90
λ°˜μ‘ν˜•
λ ‰ν† ν”Όμ•„ μ •ν˜œκ²½ κ°•μ‚¬λ‹˜μ˜ Secure & Generic C κ°•μ˜λ₯Ό λ“£κ³ , μ •λ¦¬ν•œ λ‚΄μš©μž…λ‹ˆλ‹€. 
ν•΄λ‹Ή λ‚΄μš©μ˜ μ €μž‘κΆŒμ€ μ •ν˜œκ²½ κ°•μ‚¬λ‹˜μ—κ²Œ μžˆμŠ΅λ‹ˆλ‹€.

macro function

 λ§€ν¬λ‘œ ν•¨μˆ˜λŠ” 컴파일 전에 μ „μ²˜λ¦¬κΈ°μ— μ˜ν•΄ ν…μŠ€νŠΈλ‘œ μΉ˜ν™˜μ΄ λœλ‹€. λ˜ν•œ `argument`의 νƒ€μž… μ œν•œμ΄ μ—†λ‹€λŠ” νŠΉμ§•μ„ 가지고 μžˆλ‹€. 이둜써 맀크둜 ν•¨μˆ˜λŠ” νŽΈλ¦¬ν•¨μ„ μ œκ³΅ν•˜μ§€λ§Œ, κ°„κ³Όν•  경우 μ˜¬λ°”λ₯΄μ§€ μ•Šμ€ κ²°κ³Όλ₯Ό λ°˜ν™˜ν•˜λ―€λ‘œ μ£Όμ˜ν•˜μ—¬ μ‚¬μš©ν•˜μ—¬μ•Ό ν•œλ‹€.

 

 

Side effect

#include <stdio.h>
#define TEST(X) ((X) * (X))

int main()
{
        int i = 1;
        int a = TEST(++i);
}

 κ°„λ‹¨ν•˜κ²Œ μƒκ°ν–ˆμ„ λ•Œ, ν•΄λ‹Ή μ½”λ“œλŠ” `TEST(X)`에 `++i`값을 λŒ€μž…ν•œλ‹€λ©΄ 4λΌλŠ” 값이 λ°˜ν™˜λ  것이라고 μƒκ°ν•œλ‹€. ν•˜μ§€λ§Œ μ΄λŠ” 맀크둜 ν•¨μˆ˜λ₯Ό 적절히 μ΄ν•΄ν•˜μ§€ λͺ»ν•œ 것이닀. μ‹€μ œ 값은 `(++i) * (++i)`의 값이 λ°˜ν™˜λ˜κ²Œ λœλ‹€.

 

#include <stdio.h>
#define TEST(I) (I * I * I)
// define TEST(I) ((I) * (I) * (I))
// μΈμžλ§ˆλ‹€ κ΄„ν˜Έλ‘œ λ¬Άμ–΄μ•Ό μ›ν•˜λŠ” κ²°κ³Όλ₯Ό 얻을 수 있음.

int main()
{
	int a = TEST(2 + 1);
	// int a = 2 + 1 * 2 + 1 * 2 + 1둜 됨. (κ·ΈλŒ€λ‘œ ν’€λ¦Ό.)
	printf("a = %d\n", a);

	return 0;
}

 λ§Œμ•½ μΉ˜ν™˜λΆ€μ— κ΄„ν˜Έλ₯Ό μ μš©ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄ μœ„μ™€ 같이 μƒμ΄ν•œ κ²°κ³Όλ₯Ό 직면할 수 μžˆλ‹€. μ΄λŠ” μ—°μ‚°μžμ˜ μš°μ„ μˆœμœ„ 적용과 ν•¨κ»˜ 맀크둜 ν•¨μˆ˜λ‘œ κ·ΈλŒ€λ‘œ 값듀이 풀렀버리기 λ•Œλ¬Έμ΄λ‹€. 이λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄μ„œλŠ” 적절히 κ΄„ν˜Έλ₯Ό μ‚¬μš©ν•˜μ—¬ μš°μ„ μˆœμœ„λ₯Ό 지정해주어야 ν•œλ‹€.

 

for (inti  = 0; i < 1000; i++) {
	abc();
}

 

 μœ„와 같이 반볡문 λ‚΄μ—μ„œ ν•¨μˆ˜κ°€ μ§€μ†μ μœΌλ‘œ 호좜될 경우, `abc()`κ°€ 맀크둜 ν•¨μˆ˜μ΄λ©΄ μ–΄λ–¨κΉŒ? 맀크둜 ν•¨μˆ˜μ˜ 경우 λΆˆλ¦¬λŠ” κ³³μ—μ„œ μ½”λ“œκ°€ κ·ΈλŒ€λ‘œ 듀어가기에 νš¨μœ¨μ μ΄λ‹€.

 

local? global?

#include <stdio.h>

size_t count = 0;
#define EXEC_BUMP(func) (func(), ++count)

void g(void)
{
	++count;
}

void aFunc(void)
{
	size_t count = 0;
	while (count++ < 10)
	{
		EXEC_BUMP(g);
        // μΌλ°˜μ μœΌλ‘œλŠ” λ³€μˆ˜λͺ…이 μΌμΉ˜ν•˜μ§€ μ•Šλ‹€λ©΄, extern λ³€μˆ˜λ₯Ό μ°Έμ‘°ν•˜κ² μ§€λ§Œ
        // 맀크둜 ν•¨μˆ˜κ°€ μ½”λ“œλ‚΄μ— ν’€λ¦¬κ²Œ λ˜λ©΄μ„œ auto variable을 μ°Έμ‘°ν•˜κ²Œ 됨.
	}
}

int main()
{
	aFunc();
	return 0;
}

 λ§€ν¬λ‘œ ν•¨μˆ˜κ°€ ν˜ΈμΆœλ˜λŠ” μœ„μΉ˜μ—μ„œ μ½”λ“œκ°€ κ·ΈλŒ€λ‘œ λ“€μ–΄κ°€κ²Œ λ˜λŠ” νŠΉμ„±μ„ μ΄ν•΄ν•œλ‹€λ©΄ μœ„μ™€ 같은 λ¬Έμ œμ— 직면할 수 μžˆλ‹€λŠ” 것을 μ•Œ 수 μžˆλ‹€. λ³€μˆ˜λ₯Ό μ°ΎλŠ” 경우 `local variable`μ—μ„œ `global variable` 순으둜 찾게 λœλ‹€. λ‹€λ₯΄κ²Œ νŒλ‹¨ν•œλ‹€λ©΄, 맀크둜 ν•¨μˆ˜λŠ” `global variable`을 μ°Έμ‘°ν•  것이라고 μƒκ°λ˜μ§€λ§Œ `local variable`을 μ°Έμ‘°ν•œλ‹€.

 

#include <stdio.h>

size_t count = 0;

void g(void)
{
	printf("g() 호좜, count = %u.\n", ++count);
}

typedef void (*exec_func)(void); // ν•¨μˆ˜ μ£Όμ†Œλ₯Ό λ°›λŠ” type 지정.
// parameter둜 ν•¨μˆ˜ 이름을 f둜 λ‘μ–΄μ„œ μ‚¬μš©κ°€λŠ₯ν•˜λ„λ‘.
inline void exec_bump(exec_func f) {
    f();
    ++count;
}

void aFunc(void)
{
	size_t count = 0;
	while (count++ < 10)
	{
		exec_bump(g);
        // typedefλ₯Ό 톡해 g ν•¨μˆ˜ μ‹œμž‘ μ£Όμ†Œλ₯Ό 전달.
	}
}

int main()
{
	aFunc();
	getchar();
	return 0;
}

 μž˜ μž‘μ„±ν•œ μ½”λ“œλΌλ©΄ μ€‘λ³΅λ˜λŠ” 의미의 λ³€μˆ˜λ₯Ό κ°€μ§€λŠ” 것은 쒋지 μ•Šλ‹€. ν•˜μ§€λ§Œ μœ„μ˜ 상황을 μ§λ©΄ν•˜μ§€ μ•ŠκΈ° μœ„ν•΄μ„œλŠ” `typedef`λ₯Ό ν™œμš©ν•˜λ©΄ μ›ν•˜λŠ” κ²°κ³Όλ₯Ό 얻을 수 μžˆλ‹€.

 

맀크둜둜 μ§€μ •ν•œ 포인터

#define cstring char *

int main() {
    csting ap, bp;
}

 μ΄ μ½”λ“œμ—μ„œ μ›ν•˜λŠ” κ²°κ³ΌλŠ” `char *ap`, `char *bp`이닀. ν•˜μ§€λ§Œ `char *ap`, `char bp`κ°€ μ„ μ–Έλœλ‹€. λ¬Όλ‘  μ μ ˆν•œ μ½”λ”© μŠ€νƒ€μΌμΌ 경우 이와 같이 ν•œ 쀄에 μ—¬λŸ¬ 개λ₯Ό μ„ μ–Έν•˜λŠ” 것은 잘 λͺ»λ˜μ—ˆλ‹€. μ›ν•˜λŠ” κ²°κ³Όλ₯Ό μ–»κΈ° μœ„ν•΄μ„œλŠ” `typedef char * csting`으둜 μ„ μ–Έν•˜μ—¬μ•Ό ν•œλ‹€.

 

#/## μ—°μ‚°μž ν™œμš©

 `#` μ—°μ‚°μžμ˜ 경우 `#define`μ—μ„œ μ‚¬μš©ν•˜λŠ” κ²ƒμ—μ„œ μ•Œ 수 μžˆλ“―μ΄, 토큰을 ν…μŠ€νŠΈν™” μ‹œμΌœμ£ΌλŠ” κΈ°λŠ₯을 μˆ˜ν–‰ν•œλ‹€. 이와 달리 `##`의 경우 토큰을 λ³‘ν•©μ‹œμΌœμ£ΌλŠ” κΈ°λŠ₯을 μˆ˜ν–‰ν•œλ‹€.

 

#define PRN(x, type) type##Print(x)
void charPrint(char);
void shortPrint(short);
void intPrint(int);

int main()
{
	char ch = 'A';
	short s = -1;
	int i = 2147483647;

	PRN(ch, char);
	PRN(s, short);
	PRN(i, int);

	return 0;
}

 μ΄λ₯Ό 적절히 ν™œμš©ν•œλ‹€λ©΄, `type`에 따라 ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜μ§€ μ•Šκ³  `argument`만 달리 ν•˜λŠ” μ‹μœΌλ‘œ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λŠ” κΈ°λŠ₯을 λ§Œλ“€ 수 μžˆλ‹€.

 

μ—¬λŸ¬ μ€„μ˜ 맀크둜

#include <stdio.h>
#define SWAP(x,y) \
	tmp = x; \
	x = y; \
	y = tmp

int main()
{
	int x, y, z, tmp = 0;

	printf("x = ");	scanf("%d", &x);
	printf("y = ");	scanf("%d", &y);
	printf("z = ");	scanf("%d", &z);

	if (z == 0) SWAP(x, y);
	printf("x = %d, y = %d, z = %d\n", x, y, z);
	return 0;
}

 Cμ½”λ“œλ₯Ό μž‘μ„±ν•  λ•Œ ν”νžˆ, `if`μ—μ„œ ν•œ μ€„μ˜ μ½”λ“œλ₯Ό μ‹€ν–‰μ‹œν‚€κ³ μž ν•œλ‹€λ©΄ μœ„μ™€ 같이 μž‘μ„±ν•œλ‹€. ν•˜μ§€λ§Œ μ•žμ„œ μ–ΈκΈ‰ν•˜μ˜€λ“―μ΄ 맀크둜 ν•¨μˆ˜λŠ” 호좜된 μœ„μΉ˜μ—μ„œ μ½”λ“œκ°€ 직접 λ“€μ–΄κ°„λ‹€λŠ” νŠΉμ§•μ„ 가지고 μžˆλ‹€. λ”°λΌμ„œ 이λ₯Ό λ³€κ²½ν•˜λ©΄ λ‹€μŒκ³Ό κ°™λ‹€.

 

int main()
{
    if (z == 0)
    	//SWAP 호좜
    	tmp = x;
    x = y;
    y = tmp;
}

 μ¦‰ if문의 성곡 여뢀에 상관 없이 μ•„λž˜μ˜ μ½”λ“œλŠ” 무쑰건 μˆ˜ν–‰ν•˜κ²Œ λœλ‹€. λ”°λΌμ„œ `if (z == 0) { SWAP(x, y); }`λ₯Ό μ‚¬μš©ν•œλ‹€.

 

do { \
	tmp = m; \
	x = y; \
	y = tmp; \
} while (0)

 μ€‘κ΄„ν˜Έ 없이 μ‚¬μš©ν•˜κ³ μž ν•œλ‹€λ©΄, 맀크둜λ₯Ό `do-while`둜 감싸 쀌으둜써 λ™μΌν•œ κΈ°λŠ₯을 μˆ˜ν–‰ν•˜λ„λ‘ ν•  수 μžˆλ‹€.

 

macro vs const

 μƒμˆ˜λ₯Ό μ„ μ–Έν•  λ•ŒλŠ” 2가지 방법을 μ‚¬μš©ν•œλ‹€. ν•˜λ‚˜λŠ” `macro`이고 ν•˜λ‚˜λŠ” `const`이닀. 두 가지 λͺ¨λ‘ μƒμˆ˜μ΄μ§€λ§Œ μ–΄λ–€ λͺ©μ μΈκ°€μ— 따라 λ‹€λ₯΄κ²Œ μ‚¬μš©ν•  수 μžˆλ‹€.

 

#define PI 3.14
// 파일 내에 λͺ¨λ“  ν•¨μˆ˜μ—μ„œ 같은 κ°’μœΌλ‘œ μ“°κ³  μ‹Άλ‹€λ©΄, μ£Όμ†Œμ°Έμ‘° λΆˆκ°€.
const doulbe 3.14
// 같은 파일 내에 ν•¨μˆ˜λ³„λ‘œ μƒμˆ˜λ₯Ό μ„ μ–Έν•˜κ³ μž ν•˜λŠ” 경우

 μ¦‰ `macro`λ₯Ό 톡해 μ„ μ–Έλœ μƒμˆ˜μ˜ 경우 파일 내에 λͺ¨λ“  ν•¨μˆ˜μ—μ„œ μ μš©ν•  수 μžˆλŠ” 값을 μ„ μ–Έν•  κ²½μš°μ— μ‚¬μš©ν•  수 μžˆλ‹€. 이와 달리 `const`의 경우 같은 파일 내에 ν•¨μˆ˜ λ³„λ‘œ μƒμˆ˜λ₯Ό μ„ μ–Έν•˜κ³ μž ν•˜λŠ” κ²½μš°μ— 적절히 이용될 수 μžˆλ‹€.

 

728x90
λ°˜μ‘ν˜•

'πŸ™‹β€β™‚οΈ ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄ > C' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

C: Generic Coding  (0) 2020.11.18
C: λ‹€μ–‘ν•œ 포인터  (0) 2020.11.17
C: μ •μˆ˜μ˜ λ²”μœ„  (0) 2020.11.16
C: ν‘œν˜„μ‹  (0) 2020.11.14
C: μ„ μ–Έκ³Ό μ΄ˆκΈ°ν™”  (0) 2020.11.14
λŒ“κΈ€
κΈ€ 보관함
μ΅œκ·Όμ— 올라온 κΈ€
μ΅œκ·Όμ— 달린 λŒ“κΈ€