ifdefs

이 게시물은 UniVerse BASIC에서 ifdef를 사용하는 데 한정되지만 논리는 C 및 C++에 적용되며 컴파일 시간 지시문이 있는 모든 언어를 상상합니다.

내가 NovaShell을 위해 한 일 중 하나는 조건부 컴파일을 추가하는 것이었습니다. 저는 D3와 UniVerse 모두에 동일한 프로그램을 사용하고 싶었고, 동일한 파일을 사용하여 디렉토리 생성과 같은 Windows 및 Linux 관련 작업을 수행하고 싶었습니다. 이것은 내가 ifdefs를 사용해야 한다는 것을 의미했습니다. 나는 기본적으로 몇 가지 정의문을 설정한 다음 정의된 기호를 기반으로 컴파일러가 프로그램의 다른 부분을 컴파일합니다.

이것은 궁극적으로 자체 블록에 UniVerse 특정 코드를, 다른 블록에 D3 특정 코드를 가질 수 있음을 의미했습니다. D3 코드 중 일부는 UniVerse에서 유효하지 않고 일부 UniVerse 코드는 D3에서 유효하지 않기 때문에 간단한 if 문으로 이 작업을 수행할 수 없습니다.

런타임에 데이터베이스 유형을 전달하고 필요한 특정 코드를 실행할 수 있으므로 간단한 if 문이 되었으면 좋았을 것입니다. 그러나 이것은 작동하지 않으며 어떤 영역을 제어하기 위해 ifdefs를 사용해야 했습니다. 컴파일하십시오.

$DEFINE DATABASE.UV
$DEFINE PLATFORM.LINUX


이렇게 하면 이 두 변수가 기호 테이블에 추가됩니다.

            $IFDEF PLATFORM.LINUX
                $IFDEF DATABASE.UV
                    NSH.ENTRY<1> = 'F'
                    NSH.ENTRY<2> = '/tmp/.nsh/'
                    NSH.ENTRY<3> = '/tmp/.nsh/'
                $ENDIF
                $IFDEF DATABASE.D3
                    NSH.ENTRY<1> = 'Q'
                    NSH.ENTRY<3> = 'UNIX:/tmp/.nsh/'
                $ENDIF
            $ENDIF
            $IFDEF PLATFORM.WINDOWS
                $IFDEF DATABASE.UV
                    NSH.ENTRY<1> = 'F'
                    NSH.ENTRY<2> = 'DOS:C:\.nsh\'
                    NSH.ENTRY<3> = 'DOS:C:\.nsh\'
                $ENDIF
                $IFDEF DATABASE.D3
                    NSH.ENTRY<1> = 'Q'
                    NSH.ENTRY<3> = 'DOS:C:\.nsh\'
                $ENDIF
            $ENDIF


이 코드 덩어리에는 런타임 코드와 컴파일 시간 코드가 모두 있습니다. 컴파일 시간에 컴파일러는 ifdef를 사용하여 해당 코드 블록을 파일에 남겨두어야 하는지 확인합니다. Ifdef는 "정의된 경우"를 나타냅니다. 첫 번째 경우 컴파일러는 PLATFORM.LINUX 기호가 정의되었는지 묻고 다음 코드 덩어리를 포함합니다.

보시다시피 ifdef를 중첩할 수 있습니다. 다음 ifdef는 DATABASE.UV 기호가 있는지 확인합니다. 그렇다면 해당 코드 덩어리를 포함하십시오. 이 경우 이전 정의문을 기반으로 가능한 30줄의 코드 중 궁극적으로 3줄의 코드만 남길 것입니다.

NovaShell이 ​​교차 플랫폼이 되도록 하기 위해 몇 가지 다른 위치에서 이 논리를 사용했습니다. 두 개의 프로그램을 만들고 ifdefs를 제거할 수 있습니다. ifdefs가 확실히 약간의 노이즈를 추가하기 때문입니다. 하지만 너무 많은 코드가 두 프로그램 간에 공유되므로 이것이 더 합리적이라고 생각합니다.

좋은 웹페이지 즐겨찾기