.c 파일에서 #ifdef를 피해야 하는 이유는 무엇입니까?
CC 을#if
그리고.#ifdef
헤더 파일을 제외하고는 어떤 비용을 치르더라도 피해야 합니다.입니까를 이 왜 됩니까?#ifdef
컴퓨터 파일로?
유지하기 어렵습니다.다를 보다 인터페이스를 하는 것이 .#ifdef
구현 전반에 걸쳐 확장할 수 있습니다.
예.
void foo() {
#ifdef WIN32
// do Windows stuff
#else
// do Posix stuff
#endif
// do general stuff
}
좋지 않습니다.다.foo_w32.c
그리고.foo_psx.c
와 함께
foo_w32.c:
void foo() {
// windows implementation
}
foo_psx.c:
void foo() {
// posix implementation
}
fo.h:
void foo(); // common interface
그러면 2개의 make file1:Makefile.win
,Makefile.psx
의 적절한, 를 합니다..c
파일 및 링크를 올바른 개체에 연결합니다.
약간의 수정 사항:
한다면foo()
와 같은 달라집니다.common_stuff()
2,2그냥 당신의 전화로 그것을 불러보세요.foo()
실행.
예.
common.h:
void common_stuff(); // May be implemented in common.c, or maybe has multiple
// implementations in common_{A, B, ...} for platforms
// { A, B, ... }. Irrelevant.
foo_{w32, psx}.c:
void foo() { // Win32/Posix implementation
// Stuff
...
if (bar) {
common_stuff();
}
}
에 대한 입니다.common_stuff()
에 대한 를 매개 할 수 foo()
매우 특정한 패턴을 따르지 않는 한 플랫폼당.일반적으로 플랫폼 차이는 완전히 다른 구현을 필요로 하며 이러한 패턴을 따르지 않습니다.
- 여기서는 make file을 예시적으로 사용합니다.다를 할 수 .
make
비주얼 스튜디오, CMake, 스컨스 등을 사용하는 경우 - 라 할지라도
common_stuff()
실제로는 플랫폼마다 다양한 여러 구현이 있습니다.
(질문에서 다소 벗어나 있음)
사용을 을 본 .#if(n)def/#endif
주석 대신 디버깅/isolating 코드에 사용할 블록입니다.
의견을 제시할 섹션에 이미 문서 설명이 있고 다음과 같은 해결책이 구현되어야 하는 상황을 피할 수 있도록 제안했습니다.
/* <-- begin debug cmnt if (condition) /* comment */
/* <-- restart debug cmnt {
....
}
*/ <-- end debug cmnt
대신 다음과 같습니다.
#ifdef IS_DEBUGGED_SECTION_X
if (condition) /* comment */
{
....
}
#endif
제가 보기엔 괜찮은 생각인 것 같네요.출처를 기억해서 링크할 수 있었으면 좋겠네요 :(
그러면 검색 결과를 읽을 때 코드를 읽지 않고는 코드가 입력되었는지 출력되었는지 알 수 없기 때문입니다.
OS/Platform 종속성을 위해 사용되어야 하기 때문에, 그런 종류의 코드는 io_win.c 또는 io_macos.c와 같은 파일에 있어야 하기 때문입니다.
이 규칙에 대한 나의 해석:사용자의 (알고리즘) 프로그램 로직은 전처리기 정의에 영향을 받지 않아야 합니다.코드의 기능은 항상 간결해야 합니다.다른 형태의 논리(플랫폼, 디버그)는 헤더 파일에서 추상화 가능해야 합니다.
이것은 엄격한 규칙이라기 보다는 가이드라인입니다, IMHO.그러나 저는 c-syntax 기반 솔루션이 전처리기 마법보다 선호된다는 것에 동의합니다.
조건부 컴파일은 디버깅하기 어렵습니다.프로그램이 실행될 코드 블록을 결정하기 위해서는 모든 설정을 알아야 합니다.
저는 조건부 컴파일을 사용하는 멀티 스레드 응용 프로그램을 디버깅하는 데 일주일을 보낸 적이 있습니다.문제는 식별자의 철자가 똑같지 않다는 것이었습니다. 하나 듈 1#if FEATURE_1
.#if FEATURE1
(밑줄 표시).
나는 그들을 허락하는 것에 대한 큰 지지자입니다.makefile
올바른 라이브러리 또는 개체를 포함하여 구성을 처리합니다.코드를 더 쉽게 읽을 수 있게 만듭니다.또한 대부분의 코드가 구성에 독립적이고 일부 파일만이 구성에 종속적입니다.
합리적인 목표이지만 엄격한 규칙만큼 훌륭하지는 않습니다.
인터페이스를 조건부로 선택할 수 있지만 혼란스럽고 추한 전처리기 논리로 코드를 낭비하지 않도록 하기 때문에 전처리기 조건을 헤더 파일에 저장하는 것이 좋습니다.
하지만 아래의 꾸며낸 예시처럼 보이는 코드가 아주 많고 많은 것들이 있는데, 이보다 더 좋은 대안은 없다고 생각합니다.당신이 합리적인 지침을 인용했다고 생각하지만 훌륭한 금탁지는 않습니다.
#if defined(SOME_IOCTL)
case SOME_IOCTL:
...
#endif
#if defined(SOME_OTHER_IOCTL)
case SOME_OTHER_IOCTL:
...
#endif
#if defined(YET_ANOTHER_IOCTL)
case YET_ANOTHER_IOCTL:
...
#endif
CPP는 C 또는 C++ 위에 별도의 (튜링이 완료되지 않은) 매크로 언어입니다.이처럼 주의하지 않으면 기본 언어와 혼동되기 쉽습니다.어쨌든 그것은 c++ 템플릿 대신 매크로에 대한 일반적인 논쟁입니다.그런데 #ifdef?가서 한번도 본 적 없는 다른 사람의 코드를 읽어보세요 Ifdefect가 많이 있어요
예: Reed-Solomon은 블록 단위로 상수 단위로 Galois 값을 곱합니다. http://parchive.cvs.sourceforge.net/viewvc/parchive/par2-cmdline/reedsolomon.cpp?revision=1.3&view=markup
다음과 같은 힌트가 없다면 상황을 파악하는 데 1분이 걸릴 것입니다.두 가지 버전이 있습니다. 간단한 버전과 미리 계산된 룩업 테이블(LONG MULTIPLY)이 있는 버전입니다.그래도 #if BYTE_ORDER == __LITTLE_ENDIAN을 재미있게 추적해보세요.리눅스의 바이트오더.h 항목에서 영감을 받은 le16_to_cpu 함수(정의가 #if절 안에 있음)를 사용하기 위해 그 비트를 다시 썼을 때 훨씬 읽기 쉽다는 것을 알았습니다.
빌드에 따라 다른 하위 레벨 동작이 필요한 경우 큰 함수 안에 #if stuff를 넣는 대신 어디에서나 일관된 동작을 제공하는 하위 레벨 함수에서 캡슐화를 시도합니다.
조건부 편집보다는 추상화를 선호합니다.그러나 휴대용 소프트웨어를 작성한 사람이라면 누구나 알 수 있듯이 환경 순열의 수는 엄청납니다.어떤 디자인 분야는 도움이 될 수 있지만 때로는 우아함과 일정을 맞추는 것 사이에서 선택할 수 있습니다.그런 경우에는 타협이 필요할 수도 있습니다.
완벽하게 테스트된 코드와 100% 지점 커버리지 등을 제공해야 하는 상황을 고려해 보십시오.이제 조건부 컴파일을 추가합니다.
조건부 컴파일을 제어하는 데 사용되는 각 고유 기호는 테스트해야 할 코드 변형의 수를 두 배로 증가시킵니다.그래서, 하나의 기호 - 두 개의 변형이 있습니다.두 개의 기호, 이제 코드를 컴파일하는 네 가지 다른 방법이 있습니다.뭐 이런 거.
그리고 이것은 다음과 같은 부울 테스트에만 적용됩니다.#ifdef
. 테스트가 형식이라면 문제를 쉽게 상상할 수 있습니다.#if VARIABLE == SCALAR_VALUE_FROM_A_RANGE
.
코드가 다른 C 컴파일러로 컴파일되고 컴파일러별 기능을 사용하는 경우 사용 가능한 미리 정의된 매크로를 결정해야 할 수도 있습니다.
#if #endif가 코드를 읽는 것을 복잡하게 만드는 것은 사실입니다.하지만 저는 이것을 사용하는 데 문제가 없고 여전히 강한 실제 세계 코드를 많이 보았습니다.따라서 #if #endif를 사용하는 것을 피할 수 있는 더 나은 방법이 있을지도 모르지만 적절한 주의를 기울이면 사용하는 것이 나쁘지 않습니다.
언급URL : https://stackoverflow.com/questions/1851181/why-should-ifdef-be-avoided-in-c-files
'programing' 카테고리의 다른 글
카르마 / 자스민으로 모달 인스턴스 컨트롤러를 테스트하는 장치 (0) | 2023.09.23 |
---|---|
time_t와 같이 구현 정의된 유형의 형식 지정자 (0) | 2023.09.23 |
Docker MYSQL '[2002] 연결 거부' (0) | 2023.09.23 |
JS/jQuery가 HTTP 요청 요청 헤더를 얻습니까? (0) | 2023.09.23 |
Oracle driver를 통해 Nodejs로 원격 Oracle DB에 연결 (0) | 2023.09.23 |