if-else 블록에서 'if (0)'블록의 목적은 무엇입니까?


141

내 질문은 내가 주제에서 언급 한 라인과 생산 코드 내부의 많은 곳에서 볼 수있는 라인에 관한 것입니다.

전체 코드는 다음과 같습니다.

if (0) {
    // Empty braces
} else if (some_fn_call()) {
    // actual code
} else if (some_other_fn_call()) {
    // another actual code
    ...
} else {
    // default case
}

다른 지점은 내 질문과 관련이 없습니다. if (0)여기 에 넣는 의미가 무엇인지 궁금합니다 . 중괄호가 비어 있으므로 코드 블록에 주석을 달아야한다고 생각하지 않습니다. 컴파일러가 최적화를 수행하도록 의도 했습니까? 아니면 의도가 다른가요?

나는 SO와 인터넷 에서이 명백한 사건을 찾으려고 노력했지만 성공하지 못했습니다. JavaScript에 대해서는 비슷한 질문이 있지만 C는 아닙니다. 또 다른 질문이 있습니다 .`if` 조건에서 0이 할당되면 어떻게됩니까? 'if (0)'사용법 자체가 아니라 변수에 대한 제로 할당에 대해 설명합니다.


2
그 말은 관련이없는 것 같습니다. 해당 문장의 유무에 관계없이 어셈블리 코드를 생성하면 어떤 일이 벌어지고 있는지 알 수 있습니다.
haccks

2
이것이 자동으로 생성 된 코드 일 수 있습니다.
괴물

답변:


91

나는 때때로 이것을 대칭을 위해 사용하기 때문에 나는 else if{첫 번째를 신경 쓰지 않고 내 편집기로 다른 것을 자유롭게 움직일 수있다 if.

의미 적으로

if (0) {
    // Empty braces
} else 

부분은 아무것도하지 않으며 최적화 프로그램을 사용하여 삭제할 수 있습니다.


239
개인적인 견해 : 이것이 이유 코드가있는 그대로의 이유 코드 일 수도 있지만, 그것이 타당한 이유라고 생각합니다. 코드는 작성된 것보다 자주 읽 히며,이 불필요한 코드는 독자의 구문 분석 오버 헤드를 증가시킵니다.
user694733

13
@ user694733 : if else모든 중요한 코드 경로 의 공통 접두어가 조건을 훌륭하게 정렬하고 쉽게 스캔 할 수 있다고 주장 할 수 있습니다. (이것은 주관적이며 실제로 조건과 코드 블록 안에있는 많은 것들에 달려 있습니다.)
M Oehm

72
나는 if (0) {..}파싱 ​​가능성 / 가독성 문제를 소개 하지 않는다고 생각 합니다. 약간의 C를 아는 사람에게는 분명해야합니다. 문제는 아닙니다. 문제는 다음 질문을 읽은 후의 후속 질문입니다. "도대체 그게 뭐야?" 디버깅 / 임시 목적이 아니라면 (즉, if나중에 해당 블록 을 "활성화"하려는 의도가있는 경우가 아니라면 ) 완전히 제거하는 것이 좋습니다. 기본적으로 이러한 코드를 "읽으면"독자에게 불필요한 "일시 중지"가 발생할 수 있습니다. 그리고 그것은 그것을 제거해야 할 충분한 이유입니다.
PP

77
가독성을 떨어 뜨리는 것처럼 보입니다. 프로그래머가 SO에게 무엇을 요청했는지 물어 보는 것은 너무 나빴습니다. 좋은 징조가 아닙니다.
Vectorjohn

26
이 패턴을 사용하더라도 else if조건이 상호 배타적이지 않을 수 있기 때문에 "걱정없이 편집기를 이동할 수 있는지"모르겠습니다 . 이 경우 순서가 중요합니다. 개인적으로 필자는 필요할 경우 로직 체인을 별도의 함수로 추출하여 조기 반환을if 수행하고 조기 반환을 수행 합니다.
John Wu

105

이것은 #if진술 이있는 경우 유용 할 수 있습니다.

   if (0)
   {
       // Empty block
   }
#if TEST1_ENABLED
   else if (test1())
   {
      action1();
   }
#endif
#if TEST2_ENABLED
   else if (test2())
   {
      action2();
   }
#endif

기타

이 경우 모든 (그리고 모든) 테스트를 수행 할 수 있으며 #if코드는 올바르게 컴파일됩니다. 거의 모든 컴파일러가 if (0) {}부품 을 제거합니다 . 간단한 자동 생성기는 코딩이 약간 더 쉬우므로 이와 같은 코드를 생성 할 수 있습니다. 첫 번째 활성화 된 블록을 별도로 고려할 필요는 없습니다.


5
많은 경우에 if/ else if체인은 의사 결정 트리로 많이 사용되지 않고 우선 순위가 가장 높은 조건이 "특별한"조건이 아닌 "처음 일치 조건에 따른 작업"구문으로 사용됩니다. if(0)모든 실제 브랜치가 일관된 구문을 가질 수있는 방법으로 사용 되지는 않았지만 촉진하는 일관된 구문이 마음에 듭니다.
supercat

1
이 경우에도 동일한 효과를 얻을 수 있기 때문에 유용하지 않습니다. else if라인을 두 개로 나누고 프리 프로세서 가드를 사이에두기 만하면 됩니다.
Konrad Rudolph

1
@KonradRudolph 님을 팔로우하고 있지 않습니다; 어떻게 쓰시겠습니까?
JiK

1
@JiK 나는 if (0)분기를 제거하고 else의 라인을 따라 가드로 둘러싸인 자체 라인에 있는 나머지를 다시 포맷합니다 #if TEST1_ENABLED && TEST2_ENABLED.
Konrad Rudolph

5
@KonradRudolph 가드 수를 두 배로 늘리고 언급 한 가드 조건을 세 배로 늘리고 싶다면 괜찮습니다.
홉스

44

생성 된 코드에서 사용 된 유사한 패턴을 보았습니다. 예를 들어, SQL에서 라이브러리가 다음 where절을 방출하는 것을 보았습니다 .

where 1 = 1

이것은 아마도 다른 기준을 추가하기가 더 쉬울 것입니다. 왜냐하면 모든 추가 기준 and이 첫 번째 기준인지 아닌지를 확인하기위한 추가 검사 대신 추가 될 수 있기 때문 입니다.


4
1=1항상 추가 할 수 있기 때문에 또한 "유용"입니다 where무조건, 앞에. 그렇지 않으면 비어 있는지 확인해야하며, 그렇지 않으면 where절을 생성하지 마십시오 .
Bakuriu

2
또한, 대부분의 데이터베이스는 자동으로 "제거"를합니다 1=1으로부터 WHERE그 성능에 영향을주지 않도록.
기금 모니카의 소송

7
이것은 DevOps 팀에서도 볼 수없는 SQL 쿼리를 자동으로 생성하는 라이브러리에서 허용됩니다. 여러 번 작성하고 읽어야하는 고급 코드에서는 "허용 될 수 없습니다".
phagio

이것은 알려지지 않은 최종 조건으로 어떤 종류의 동적 SQL 을 생성 할 때 실제로 편리한 접근 방식 입니다.
Skipper

1
@freakish 실제로 나는 그 반대를 썼습니다 : 개발자가 유지 관리하는 고급 기능 코드가 아니라 읽을 수 없기 때문에 읽기 어려운 구문은 생성 된 코드에서 허용됩니다.
phagio

44

작성된 바와 if (0) {}같이이 절은 아무 것도 컴파일하지 않습니다.

이 사다리의 상단에있는 절의 기능은 0a 1또는 로 변경하여 다른 모든 기능을 한 번에 (디버깅 또는 비교 목적으로) 일시적으로 비활성화 할 수있는 쉬운 장소를 제공하는 것 true입니다.


2
못을 박았다 디버깅 외에 다른 이유를 볼 수 없었습니다.
tfont

16

나는 어떤 최적화도 확신하지 못하지만 내 2 센트 :

이것은 하나의 주요 조건이 제거 된 코드 수정 (초기 if블록 의 함수 호출 )으로 인해 발생했지만 개발자 / 관리자

따라서 관련 if블록 을 제거하는 대신 조건을 변경하고 계속 진행 if(0)했습니다.


3
하지가 if(0)너무 지점의 범위를 감소?
David Szalai

1
@DavidSzalai 완전히 (완전하지는 않음) – 최대 1 (이전 2에서) 감소 할 것입니다. 그러나 한 번의 히트는 내가 아는 한도 내에서 커버리지에 필요합니다.
Sourav Ghosh

15

코드 썩음입니다.

어떤 시점에서 "만약"이 유용한 일을했다면 상황이 바뀌었고 평가중인 변수가 제거되었을 수도 있습니다.

시스템을 수정 / 변경 한 사람은 가능한 한 시스템의 논리에 영향을 미치 므로 코드를 다시 컴파일해야합니다. 그래서 그는 빠르고 쉬운 "if (0)"을 남기고 자신이하고 싶은 것이 무엇인지 완전히 확신하지 못합니다. 그는 시스템을 작동시키고 시스템을 완전히 고치기 위해 돌아 가지 않습니다.

그런 다음 다음 개발자가 의도적으로 수행되었다고 생각 하고 코드의 해당 부분 만 주석 처리합니다 (어쨌든 평가되지 않으므로). 다음에 코드를 만질 때 해당 주석이 제거됩니다.


2
예. 고대 코드의 경우 한 번에 하나의 데드 코드 제거 변경을 수행하십시오. 나는 "죽은 (dead)"코드에 대해 슬래시 앤 번 (slash-and-burn)을 겪은 횟수를 세고 계산할 수 없었습니다.
Julie in Austin

15

아직 언급되지 않은 한 가지 가능성 :이 if (0) {회선은 중단 점에 편리한 지점을 제공 할 수 있습니다.

디버깅은 종종 최적화되지 않은 코드에서 수행되므로 항상 거짓 테스트가 수행되고 중단 점이 설정 될 수 있습니다. 프로덕션 용으로 컴파일하면 코드 라인이 최적화됩니다. 겉보기에 쓸모없는 라인은 릴리스 빌드에 영향을 미치지 않고 개발 및 테스트 빌드 기능을 제공합니다.

위의 다른 좋은 제안도 있습니다. 목적이 무엇인지 실제로 아는 유일한 방법은 저자를 추적하고 물어 보는 것입니다. 소스 코드 제어 시스템이 도움이 될 수 있습니다. ( blame유형 기능을 찾으십시오 .)


9

템플릿 언어를 사용하여 생성 된 사전 확장 JavaScript에서 도달 할 수없는 코드 블록을 보았습니다.

예를 들어, 읽고있는 코드는 당시 서버 측에서만 사용 가능한 변수에 의존하는 첫 번째 조건을 미리 평가 한 서버에서 붙여 넣을 수있었습니다.

if ( ${requestIsNotHttps} ){ ... }else if( ...

한 번 사전 컴파일 된 것입니다.

if ( 0 ){ ... }else if ( ...

이것이 내가 당신이 열정을 나타내는 프로 재활용 코더 시대의 잠재적 인 낮은 키보드 활동을 상대화하는 데 도움이되기를 바랍니다!


1
유비쿼터스 자동화 시대에는 실제 생성에 더 많은 시간을 할애 할 수 있기 때문에 자동 생성 코드에 더 의존해야한다는 데 동의합니다. 그러나 지금은 정확히 내가 관심을 갖는 것은이 모든 것이 어떻게 구성되어 있는지입니다.
Zzaponka

8

이 구조는 C에서 형식 안전성을 가진 일반 프로그래밍을 구현하는 데 사용될 수 있으며 컴파일러가 도달 할 수없는 코드를 여전히 확인한다는 사실에 의존합니다.

// this is a generic unsafe function, that will call fun(arg) at a later time
void defer(void *fun, void *arg);

// this is a macro that makes it safer, by checking the argument
// matches the function signature
#define DEFER(f, arg) \
   if(0) f(arg); \              // never actually called, but compile-time checked
   else defer(f, (void *)arg);  // do the unsafe call after safety check

void myfunction(int *p);

DEFER(myfunction, 42);     // compile error
int *b;
DEFER(myfunction, b);      // compiles OK

6

나는 그것이 나쁜 코드라고 생각합니다. 컴파일러 탐색기에서 간단한 예제를 작성하면 gcc와 clang if (0)에서 최적화가 완전히 비활성화 된 경우에도 블록에 대한 코드가 생성 되지 않습니다.

https://godbolt.org/z/PETIks

if (0)원인 을 제거하면서 놀고 있으면 생성 된 코드가 변경되지 않으므로 이것이 최적화가 아니라고 결론을 내립니다.

if나중에 제거 된 상단 블록에 무언가있을 수 있습니다 . 요컨대 제거하면 똑같은 코드가 생성되는 것처럼 보이므로 자유롭게 수행하십시오.


6

말했듯이, 0은 거짓으로 평가되며 분기는 컴파일러에 의해 최적화 될 것입니다.

또한 새로운 기능이 추가되고 킬 스위치가 필요한 코드 (이 기능에 문제가있는 경우 그냥 끌 수 있음)와 나중에 킬 스위치가 제거 된 코드에서 이것을 보았습니다. 프로그래머도 분기를 제거하지 않았습니다. 예 :

if (feature_a_active()) {
    use_feature_a();
} else if (some_fn()) {
   ...

되었다

if (0) {
   // empty
} else if (some_fn()) {
   ...

1

블록 1을 넣는 것만으로이 블록을 디버깅하는 데 도움이됩니다. 또한 else else 블록을 확장 할 수 있습니다.


1
    Actually according to my opinion, if we put any variable for checking inside
    e.g:-
public static void main(string args[])
{
        var status;
        var empList=_unitofWork.EmpRepository.Get(con=>con.isRetired==true);
        //some code logic 
        if(empList.count>0)
        {
          status=true;
        }
        if(status)
        {
         //do something
        }
        else
        {
        //do something else
        }
}
     if then its dynamically get the value in run time and invoke the logic inside it, else its simply extra line of code i guess.

    Anybody have any depth knowledge why this thing is used....or agree with me.
    kindly respond. 

1

@PSkocik의 대답은 괜찮지 만 2 센트를 더합니다. 내가 이것을 주석으로, 또는 대답으로해야하는지 확실하지 않다; 다른 사람들이 볼만한 가치가있는 IMHO 인 반면 후자는 종종 보이지 않기 때문에 후자를 선택한다.

가끔씩 만 사용할뿐 아니라

if(0) {
   //deliberately left empty
} else if( cond1 ) {
   //deliberately left empty
} else if( cond2 ) {
   //deliberately left empty
...
} else {
   // no conditions matched
}

그러나 나는 또한 때때로

if( 1 
    && cond1 
    && cond2
    ...
    && condN
) {

또는

if( 0 
    || cond1 
    || cond2
    ...
    || condN
) {

복잡한 조건. 같은 이유로 편집하기 쉽고 #ifdef 등

그 문제에 대해서는 Perl에서 할 것입니다

@array = (  
    elem1,
    elem2,
    ...
    elem1,
) {
  • 목록 끝에 쉼표를 적어 둡니다. 쉼표가 C 및 C ++ 목록에서 구분 기호인지 구분 기호인지 잊어 버렸습니다. IMHO 이것은 우리가 배운 것 중 하나입니다. [ Perl의 후행 쉼표는 나쁜 습관입니까? 쉼표]는 좋은 것입니다. 새로운 표기법과 마찬가지로 익숙해지는 데 시간이 걸립니다.

if(0)코드를 lisp와 비교합니다.

(cond   (test1    action1)
   (test2    action2)
   ...
   (testn   actionn))

당신이 짐작했듯이

(cond   
   (test1    action1)
   (test2    action2)
   ...
   (testn   actionn)
)

나는 때때로 더 인간이 읽을 수있는 구문이 어떻게 생겼는지 상상하려고 노력했다.

혹시

IF
:: cond1 THEN code1
:: cond2 THEN code2
...
:: condN THEN codeN
FI

Dikstra의 [ https://en.wikipedia.org/wiki/Guarded_Command_Language#Selection:_if][Guarded Command Language] 에서 영감을 받았습니다 .

그러나이 구문은 조건이 병렬로 평가되는 반면 if...else-if조건에 대한 순차적이고 우선 순위가 높은 평가를 의미합니다.

다른 프로그램을 생성하는 프로그램을 작성할 때 이러한 작업을 시작했습니다. 특히 편리한 곳입니다.

인텔의 오래된 iHDL을 사용하여 RTL을 작성할 때 다음과 같은 코드를 작성했습니다.

   IF 0 THEN /*nothing*/
   **FORC i FROM 1 TO 10 DOC** 
   ELSE IF signal%i% THEN    
      // stuff to do if signal%i% is active
   **ENDC** 
   ELSE   
      // nothing matched 
   ENDIF

여기서 FORC..DOC..ENDC매크로 전 처리기 루프 구조는 다음과 같이 확장됩니다.

   IF 0 THEN /*nothing*/
   ELSE IF signal1 THEN    
      // stuff to do if signal1 is active
   ELSE IF signal2 THEN    
      // stuff to do if signal2 is active
   ...
   ELSE IF signal100 THEN    
      // stuff to do if signal100 is active
   ELSE   
      // nothing matched 
   ENDIF

이것은 비 할당적인 단일 할당 코드이므로 첫 번째 설정 비트 찾기와 같은 작업을 수행해야하는 경우 상태 변수를 설정할 수 없습니다.

   IF 0 THEN /*nothing*/
   ELSE IF signal1 THEN    
      found := 1
   ELSE IF signal2 THEN    
      found := 2
   ...
   ELSE IF signal100 THEN    
      found := 100
   ELSE   
      // nothing matched 
   ENDIF

그것을 생각해 보니, 이것은 내가 그런 구조물을 처음 만난 곳 일 수 있습니다.

BTW, if (0) 스타일에 대한 반대 의견-else-if 조건은 순차적으로 종속적이며 임의로 재정렬 할 수 없음-RTL의 AND 및 OR 및 XOR 논리에는 적용되지 않지만 단기에는 적용됩니다 회로 && 및 ||.


-1

예를 들어 오류를 처리하는 데 사용되는 것을 보았습니다.

if(0){
lable1:
   //do something
}
if(0){
lable2:
   //do something
}
.
.
and so on.

if(condition_fails)
   goto lable1;

이것은 goto가 오류를 관리하는 데 사용될 때 유용 할 수 있으며 명령문은 오류가 발생할 때만 실행됩니다. 나는 매우 오래된 C 코드 (함수 인수가 '()'외부에 쓰여지는 곳)에서 이것을 보았지만, 지금 아무도 이것을 따르는 것으로 생각하지 마십시오.


-2

나는 이것을 몇 번 보았습니다. 가장 가능성이 높은 이유는 코드의 이전 / 다른 버전 / 분기에서 무언가를 평가하거나 디버깅하기 위해 가능한 if(0)것으로 생각합니다. .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.