development

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

big-blog 2020. 6. 29. 07:31
반응형

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 if 구문은 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.
}

So I am sure that the people who developed the MISRA guidelines had the switch-like if-else if intention in mind.

In the end, it comes down for them to defining precisely what is meant with an "if ... else if construct"


The basic reason is probably code coverage and the implicit else: how will the code behave if the condition is not true? For genuine testing, you need some way to see that you have tested with the condition false. If every test case you have goes through the if clause, your code could have problems in the real world because of a condition that you did not test.

However, some conditions may properly be like Example 1, like on a tax return: "If the result is less than 0, enter 0." You still need to have a test where the condition is false.


Logically any test implies two branches. What do you do if it is true, and what do you do if it is false.

For those cases where either branch has no functionality, it is reasonable to add a comment about why it doesn't need to have functionality.

This may be of benefit for the next maintenance programmer to come along. They should not have to search too far to decide if the code is correct. You can kind of Prehunt the Elephant.

Personally, it helps me as it forces me to look at the else case, and evaluate it. It may be an impossible condition, in which case i may throw an exception as the contract is violated. It may be benign, in which case a comment may be enough.

Your mileage may vary.


Most the time when you just have a single if statement, it's probably one of reasons such as:

  • Function guard checks
  • Initialization option
  • Optional processing branch

Example

void print (char * text)
{
    if (text == null) return; // guard check

    printf(text);
}

But when you do if .. else if, it's probably one of reasons such as:

  • Dynamic switch-case
  • Processing fork
  • Handling a processing parameter

And in case your if .. else if covers all possibilities, in that case your last if (...) is not needed, you can just remove it, because at that point the only possible values are the ones covered by that condition.

Example

int absolute_value (int n)
{
    if (n == 0)
    {
        return 0;
    }
    else if (n > 0)
    {
        return n;
    }
    else /* if (n < 0) */ // redundant check
    {
        return (n * (-1));
    }
}

And in most of these reasons, it's possible something doesn't fit into any of the categories in your if .. else if, thus the need to handle them in a final else clause, handling can be done through business-level procedure, user notification, internal error mechanism, ..etc.

Example

#DEFINE SQRT_TWO   1.41421356237309504880
#DEFINE SQRT_THREE 1.73205080756887729352
#DEFINE SQRT_FIVE  2.23606797749978969641

double square_root (int n)
{
         if (n  > 5)   return sqrt((double)n);
    else if (n == 5)   return SQRT_FIVE;
    else if (n == 4)   return 2.0;
    else if (n == 3)   return SQRT_THREE;
    else if (n == 2)   return SQRT_TWO;
    else if (n == 1)   return 1.0;
    else if (n == 0)   return 0.0;
    else               return sqrt(-1); // error handling
}

This final else clause is quite similar to few other things in languages such as Java and C++, such as:

  • default case in a switch statement
  • catch(...) that comes after all specific catch blocks
  • finally in a try-catch clause

Our software was not mission critical, yet we also decided to use this rule because of defensive programming. We added a throw exception to the theoretically unreachable code (switch + if-else). And it saved us many times as the software failed fast e.g. when a new type has been added and we forgot to change one-or-two if-else or switch. As a bonus it made super easy to find the issue.


Well, my example involves undefined behavior, but sometimes some people try to be fancy and fails hard, take a look:

int a = 0;
bool b = true;
uint8_t* bPtr = (uint8_t*)&b;
*bPtr = 0xCC;
if(b == true)
{
    a += 3;
}
else if(b == false)
{
    a += 5;
}
else
{
    exit(3);
}

You probably would never expect to have bool which is not true nor false, however it may happen. Personally I believe this is problem caused by person who decides to do something fancy, but additional else statement can prevent any further issues.


I'm currently working with PHP. Creating a registration form and a login form. I am just purely using if and else. No else if or anything that is unnecessary.

If user clicks submits button -> it goes to the next if statement... if username is less than than 'X' amount of characters then alert. If successful then check password length and so on.

No need for extra code such as an else if that could dismiss reliability for server load time to check all the extra code.

참고URL : https://stackoverflow.com/questions/35053371/what-is-the-benefit-of-terminating-if-else-if-constructs-with-an-else-clause

반응형