#define 이 왜?

1. 상수를 정의할 때,

디버깅이 안된다.

왜 디버깅이 안될까?

=> 컴파일 시점에 상수로 바꾼다.

=> symbol table에 들어가지 않는다.

요새는 ide가 해주겠지만, 에러 로그 등에서 확인할 때, 상수명이 아니라 153.2121 같이 숫자 자체가 찍히기 때문에 디버깅하기 어려워 질 수 있다.

#include <iostream>
#define ASPECT_RATIO 1.653

void func(float a);

int main()
{
    if (ASPECT_RATIO > 2) {
        // do someting;
    }

    // 1000줄 코드...

    func(ASPECT_RATIO);

    // 1000줄 코드...

    std::cout << ASPECT_RATIO;
}

이 코드에서 translation unit을 만들면 어떻게 될까?

clang -E fileName.cpp > fileName.pre

이런 식으로 상수로 바뀐다.

symbol table은 무엇일까?

assembler의 symbol table, compiler의 symbol table이 따로 존재한다. 지금은 compiler level의 symbol table을 알아보자.

- 컴파일러에 의해 생성되고 관리되는 "변수명", "함수명", objects, classes, interfaces 등에 대한 자료구조이다.

- 심볼 테이블은 symbol name, type, scope로 구성되고, 드물게 주소가 포함될 때도 있다.

- 컴파일러의 Analysis, Synthesis 단계 모두에서 해당 기호가 정의되었는지, 정확한지 검증하기 위해 사용되고, 이를 통해 중간 코드나 타겟 코드를 만들게 된다.

- 링킹과정에서 링커가 심볼 테이블을 보

- 더 자세한 내용은 아래 링크를 보자.(허수는 안보고 넘어감)

https://www.tutorialspoint.com/compiler_design/compiler_design_symbol_table.htm

https://iq.opengenus.org/symbol-table-in-compiler/

대신에 const 또는 enum을 사용해보자.

const double AspectRatio = 1.653;
class MyClass { private: enum { NumTurns = 5 } };

2. 매크로 함수를 만들때,

매크로 함수 인자로 표현식을 넣었다면, 평가를 여러번하는 오류가 발생할 수 있다.

이런 문제를 해결하기 위해 인라인 함수로 대체해보자.

매크로 처럼 효율적이고, 타입 안정성까지 취할 수 있다.

#define CALL_WITH_MAX(a, b) f((a) > (b) ? (a) : (b))
이런 매크로 함수가 있을 때,

int a = 5;
CALL_WITH_MAX(++a, 0);
CALL_WITH_MAX(++a, 10);

평가가 여러번 될 수 있다.

+ Recent posts