[c] else 절로 if … else if 구문을 종료하면 어떤 이점이 있습니까?

우리 조직에는 다음과 같은 필수 코딩 규칙이 있습니다 (설명없이).

if… else if 구문은 else 절로 끝나야합니다

예 1 :

if ( x < 0 )
{
   x = 0;
} /* else not needed */

예 2 :

if ( x < 0 )
{
    x = 0;
}
else if ( y < 0 )
{
    x = 3;
}
else    /* this else clause is required, even if the */
{       /* programmer expects this will never be reached */
        /* no change in value of x */
}

어떤 에지 케이스가 처리하도록 설계 되었습니까?

그 이유에 대해서도 나에게 관심이있는 것은 예 1 은 필요하지 else않지만 예 2 는 필요하기 때문이다 . 그 이유가 재사용 성과 확장 성 else이라면 두 경우 모두에 사용해야 한다고 생각 합니다.



답변

다른 답변에서 언급했듯이 이는 MISRA-C 코딩 지침에 따른 것입니다. 목적은 미션 크리티컬 프로그래밍에 자주 사용되는 개념 인 방어 프로그래밍입니다.

즉, 모든입니다 if - else if와 반드시 끝 else, 모든 switchA를 반드시 끝 default.

이에 대한 두 가지 이유가 있습니다.

  • 자체 문서화 코드. 당신이를 작성하는 경우 else만은 비워두고 그 의미 : “나는 확실히 시나리오도 고려했다 if이나 else if해당”.

    작성하지 else가 의미 : “중 하나를 나는 어느 시나리오로 간주 if하거나 else if해당를, 또는 내가 완전히 고려 잊고 지방 버그가 내 코드에 바로 여기 가능성이있다”.

  • 런 어웨이 코드를 중지하십시오. 미션 크리티컬 한 소프트웨어에서는 가능성이 거의없는 강력한 프로그램을 작성해야합니다. 그래서 당신은 같은 코드를 볼 수 있습니다

    if (mybool == TRUE)
    {
    }
    else if (mybool == FALSE)
    {
    }
    else
    {
      // handle error
    }

    이 코드는 PC 프로그래머와 컴퓨터 과학자들에게는 완전히 별개 일 것이지만, “mybool”이 어떤 이유로 든 손상된 경우를 포착하기 때문에 미션 크리티컬 소프트웨어에서는 완벽하게 이해됩니다.

    역사적으로 EMI / 노이즈로 인해 RAM 메모리가 손상 될 우려가 있습니다. 이것은 오늘날 큰 문제가 아닙니다. 코드의 다른 곳에있는 버그로 인해 메모리 손상이 발생할 가능성이 훨씬 높습니다. 잘못된 위치에 대한 포인터, 범위를 벗어난 버그, 스택 오버플로, 런 어웨이 코드 등

    대부분의 경우 구현 단계에서 버그를 작성했을 때 이와 같은 코드가 다시 등장합니다. 디버그 기술로도 사용될 수 있음을 의미합니다. 작성중인 프로그램이 버그를 작성했을 때 알려줍니다.


편집하다

else매번 왜 필요하지 않은지 에 관해서 if:

if-else또는 if-else if-else완전히는 변수가 가질 수있는 가능한 모든 값을 포함한다. 그러나 if모든 가능한 값을 다루기 위해 반드시 명확한 진술이 필요한 것은 아니며 훨씬 더 광범위하게 사용됩니다. 대부분의 경우 특정 조건을 확인하고 충족되지 않으면 아무것도하지 마십시오. 그렇다면 else사건 을 다루기 위해 방어 프로그래밍을 작성하는 것은 의미가 없습니다 .

또한 else매번 빈칸을 썼다면 코드를 완전히 어지럽 힐 것이다 if.

MISRA-C : 2012 15.7은 왜 else필요하지 않은지에 대한 근거를 제시 하지 않고 단지 다음과 같이 말합니다.

참고 : else간단한 if
진술 에는 최종 진술이 필요하지 않습니다 .


답변

귀사는 MISRA 코딩 지침을 따랐습니다. 이 규칙을 포함하지만 MISRA-C : 2004 의이 지침에는 몇 가지 버전이 있습니다 .

규칙 14.10 (필수) : if if else else 구문은 else 절로 종료해야한다.

이 규칙은 if 문 뒤에 하나 이상의 else if 문이 올 때마다 적용됩니다. 결승전 if다음에는 else
진술이 이어져야 한다 . 간단한 if진술 의 경우 진술을 else
포함시킬 필요는 없습니다. 최종 else
진술에 대한 요구 사항 은 방어 프로그래밍입니다. else문 중 적절한 조치를 취하거나 어떤 조치도 취하지 이유에 대한 적절한 설명을 포함해야한다. 이는 성명서에 최종 default조항 이 있어야한다는 요구 사항과 일치 switch합니다. 예를 들어이 코드는 간단한 if 문입니다.

if ( x < 0 )
{
 log_error(3);
 x = 0;
} /* else not needed */

다음 코드는 if, else if구문을 보여줍니다

if ( x < 0 )
{
 log_error(3);
 x = 0;
}
else if ( y < 0 )
{
 x = 3;
}
else /* this else clause is required, even if the */
{ /* programmer expects this will never be reached */
 /* no change in value of x */
}

2004 버전을 대체하고 새 프로젝트에 대한 현재 권장 사항 인 MISRA-C : 2012 에는 동일한 규칙이 있지만 번호는 15.7 입니다.

예 1 :
단일 if 문 프로그래머가 n 개의 조건을 확인하고 단일 작업을 수행해야 할 수도 있습니다.

if(condition_1 || condition_2 || ... condition_n)
{
   //operation_1
}

정기적으로 사용하는 경우에는 항상 작업을 수행 할 필요가 없습니다 if.

예 2 :
여기서 프로그래머는 n 개의 조건을 확인하고 여러 작업을 수행합니다. 일반 사용에서 if..else if처럼 switch기본적 같은 작업을 수행해야 할 수 있습니다. 따라서 elsemisra 표준에 따라 사용법 이 필요합니다

if(condition_1 || condition_2 || ... condition_n)
{
   //operation_1
}
else if(condition_1 || condition_2 || ... condition_n)
{
  //operation_2
}
....
else
{
   //default cause
}

이 출판물의 현재 및 과거 버전은 MISRA 웹 스토어 를 통해 구입할 수 있습니다 ( 를 통해 ).


답변

이것은 모든 스위치에서 기본 사례를 요구하는 것과 같습니다.

그렇지 않으면 프로그램의 코드 적용 범위 가 줄어 듭니다 .


리눅스 커널이나 안드로이드 코드를 다른 플랫폼으로 포팅 한 경험에서 여러 번 우리는 뭔가 잘못하고 logcat에서 다음과 같은 오류가 발생합니다.

if ( x < 0 )
{
    x = 0;
}
else if ( y < 0 )
{
    x = 3;
}
else    /* this else clause is required, even if the */
{       /* programmer expects this will never be reached */
        /* no change in value of x */
        printk(" \n [function or module name]: this should never happen \n");

        /* It is always good to mention function/module name with the
           logs. If you end up with "this should never happen" message
           and the same message is used in many places in the software
           it will be hard to track/debug.
        */
}


답변

약 5 년 전에이 작업을 수행했기 때문에 간단한 설명 만 있습니다.

“널 else( null)” 문 (및 불필요 {..}) 을 포함하는 구문 적 요구 사항은 (대부분의 언어에서) 없으며 “간단한 프로그램”에서는 필요하지 않습니다. 그러나 실제 프로그래머는 “간단한 작은 프로그램”을 작성하지 않으며, 중요하게도 한 번 사용 된 다음 폐기 될 프로그램을 작성하지 않습니다.

if / else를 작성할 때 :

if(something)
  doSomething;
else
  doSomethingElse;

모든 것이 단순 해 보이며 추가 시점조차 거의 보지 못합니다 {..}.

그러나 언젠가는 몇 달이 지난 지금, 다른 프로그래머 (이러한 실수를 저 지르지 않을 것입니다!)는 프로그램을 “강화”하고 설명을 추가해야합니다.

if(something)
  doSomething;
else
  doSomethingIForgot;
  doSomethingElse;

갑자기 다리 doSomethingElse에 있어야한다는 것을 잊어 버렸습니다 else.

그래서 당신은 좋은 작은 프로그래머이며 항상을 사용 {..}합니다. 그러나 당신은 쓴다 :

if(something) {
  if(anotherThing) {
    doSomething;
  }
}

새로운 아이가 자정을 변경할 때까지 모든 것이 좋았습니다.

if(something) {
  if(!notMyThing) {
  if(anotherThing) {
    doSomething;
  }
  else {
    dontDoAnything;  // Because it's not my thing.
  }}
}

그렇습니다. 형식이 잘못 되었으나 프로젝트 코드의 절반이됩니다. “자동 포맷터”는 모든 #ifdef문장에 의해 볼 릭스가됩니다 . 물론 실제 코드는이 장난감 예제보다 훨씬 복잡합니다.

불행히도 (또는 아닙니다), 나는 몇 년 동안 이런 종류의 일을하지 않았으므로 신선한 “실제”예제를 염두에 두지 않습니다.


답변

이것은 나중에 참조를 들어, 코드를 더 쉽게 읽을 수 있도록하고 마지막으로 처리 남아있는 경우가 있음을 나중에 검토에, 명확하게하기위한 것입니다 else이다 아무것도 할 그들이 첫눈에 어떻게 든 간과하지 않습니다 그래서, 사례.

이것은 좋은 프로그래밍 관행으로, 코드를 재사용 하고 확장 할 수있게 합니다.


답변

이전 답변에 추가하고 부분적으로 모순하고 싶습니다. 식에 대해 생각할 수있는 값의 전체 범위를 포함해야하는 스위치와 같은 방식으로 if-else를 사용하는 것이 일반적이지만 일반적으로 가능한 범위의 조건이 완전히 적용되는 것은 아닙니다. 스위치 구성 자체에 대해서도 마찬가지입니다. 따라서 모든 나머지 값을 포착하고 어쨌든 필요하지 않은 경우 어설 션 보호 장치로 사용할 수있는 기본 절을 사용해야한다는 요구 사항이 있습니다.

질문 자체에는 좋은 반례가 있습니다. 두 번째 조건은 x와 전혀 관련이 없습니다 (스위치 기반 변형보다 유연한 경우 기반 변형을 선호하는 이유입니다). 이 예에서 조건 A가 충족되면 x가 특정 값으로 설정되어야합니다. A가 충족되지 않으면 조건 B가 테스트됩니다. 충족되면 x는 다른 값을 받아야합니다. A와 B가 모두 충족되지 않으면 x는 변경되지 않습니다.

여기서 우리는 독자에 대한 프로그래머의 의도에 대해 주석을 달기 위해 비어있는 else 브랜치를 사용해야 함을 알 수 있습니다.

반면에, 가장 최근의 가장 최근의 if 문에 else 절이 왜 필요한지 알 수 없습니다. C에서는 ‘else if’와 같은 것이 없습니다. if와 else 만 있습니다. 대신, MISRA에 따르면, 구조는 공식적으로 이런 식으로 들여 쓰기해야합니다 (그리고 여는 중괄호를 자체 줄에 넣어야하지만 좋아하지는 않습니다).

if (A) {
    // do something
}
else {
    if (B) {
        // do something else (no pun intended)
    }
    else {
        // don't do anything here
    }
}

MISRA가 모든 브랜치 주위에 중괄호를 넣으라고 요청하면 “if … else if constructs”라고 언급함으로써 모순됩니다.

중첩의 다른 나무, 경우에 사람은 추함을 상상할 수있는 보조 노트에 여기를 참조하십시오 . 이제이 구조를 어느 곳에서나 임의로 확장 할 수 있다고 상상해보십시오. 그런 다음 마지막에 else 절을 ​​요청하지만 다른 곳에서는 그렇지 않습니다.

if (A) {
    if (B) {
        // do something
    }
    // you could to something here
}
else {
    // or here
    if (B) { // or C?
        // do something else (no pun intended)
    }
    else {
        // don't do anything here, if you don't want to
    }
    // what if I wanted to do something here? I need brackets for that.
}

따라서 MISRA 지침을 개발 한 사람들은 의도가 있다면 스위치 형 if-else를 가지고 있다고 확신합니다.

결국, “if … else if construct”의 의미를 정확하게 정의하는 것은 그들이 내려온 것입니다.


답변

기본적인 이유는 아마도 코드 커버리지와 암시 적 다른 것입니다. 조건이 true가 아닌 경우 코드는 어떻게 작동합니까? 실제 테스트의 경우 false 조건으로 테스트했는지 확인할 수있는 방법이 필요합니다. 모든 테스트 사례가 if 절을 거치면 테스트하지 않은 조건으로 인해 실제 코드에서 문제가 발생할 수 있습니다.

그러나 세금 환급과 같이 일부 조건은 예 1과 동일 할 수 있습니다. “결과가 0보다 작 으면 0을 입력하십시오.” 여전히 조건이 거짓 인 테스트가 필요합니다.