ProgramingTip

C for 루프의 조건에서 상수 대신에 필요한 이유는 무엇입니까?

bestdevel 2020. 12. 14. 20:38
반응형

C for 루프의 조건에서 상수 대신에 필요한 이유는 무엇입니까?


많은 프로그래밍 대회에서 사람들이 이런 유형의 for루프를 작성하는 것을 보았습니다.

for(i = 0; i < (1 << 7); i++)

내가 뭔가를 놓치고 있지 않는 한, 그것은

for(i = 0; i < 128; i++)

(1 << 7)버전을 사용하는 이유는 무엇입니까?
불필요한 오버 헤드가 보관할 때마다 조건을 계산하지 않을 것입니까?


예, 그들은 행동면에서 동등합니다.

(1 << 7) 사용을 사용합니까?

2의 거듭 제곱이라는 것을 문서화하는 데 사용하는 것입니다.

매번 조건을 계산하는 것은 오버 헤드 관리합니다! 나는 그 이유를 수 없습니다!

별로, 어떤 정상 컴파일러는 1 << 7대체로 128같은 공연을하고 루프를 대체하게됩니다.

(C11, 6.6p2) "상수 있습니다. 작동이 아닌 번역 중에 평가 될 수 있으므로"상수가있는 모든 위치에서 사용할 수 있습니다.


각 옵션을 일반 영어로 번역 해 보겠습니다.

for(i = 0; i < (1 << 7); i++) // For every possible combination of 7 bits
for(i = 0; i < 128; i++)      // For every number between 0 and 127

두 경우 모두 실행 동작이 동일해야합니다.

사실, 괜찮은 컴파일러라고 가정하면 어셈블리 코드도 동일해야합니다.

따라서 첫 번째 옵션은 기본적으로 "성명을 작성하기"위해 사용됩니다.

두 번째 옵션을 사용하고 주석을 추가 할 수도 있습니다.


1 << 7상수 내부이고 컴파일러는이를 128, 런타임에 오버 헤드가없는 것처럼 처리합니다 .

루프 본문이 제외가 사용하는 이유를 말하기 어렵습니다. 아마도 그것은 7 비트와 관련된 것을 반복하는 루프 일 수 있습니다.


(1 << 7) 사용을 사용합니까?

그것은 문서의 한 형태이며, 마법의 숫자가 아니라 코드를 나타내는 사람에게 의미있는 2^7( 2의 7)입니다. 최신 최적화 컴파일러는 두 예제 모두에 대해 똑같은 양식을 사용하는 데 필요한 비용이 발생하여 추가 코드를 생성합니다.

godbolt사용하여 여러 버전의 gcc, clang에서 실제로인지 확인할 수 있습니다 icc. 부작용이있는 간단한 예제를 사용하여 코드가 완전히 최적화되지 않습니다.

#include <stdio.h>

void forLoopShift()
{
  for(int i = 0; i < (1 << 7); i++)
  {
    printf("%d ", i ) ;
  }
}

void forLoopNoShift()
{
  for(int i = 0; i < 128; i++)
  {
        printf("%d ", i ) ;
  }
}

코드의 관련 부분에 대해 둘 다 다음을 생성하는 것을 볼 수 있습니다 .

cmpl    $128, %ebx

우리가 가진 것은 C11 표준 섹션 상수 표현식 초안에 정의 된 정수 상수 표현식입니다 .6.6

정수 상수 표현식 117)은 정수 유형을 가져야하며 정수 상수, 열거 상수, 문자 상수, 결과가 정수 상수 인 표현식의 크기 인 피연산자 만 가져야합니다. [...]

과:

상수 표현식은 할당, 증가, 감소, 함수 호출 또는 쉼표 연산자를 포함하지 않아야합니다. 단, 평가되지 않는 하위 표현식에 포함 된 경우는 예외입니다 .115)

번역하는 동안 상수 표현식이 평가 될 수 있음을 알 수 있습니다.

상수 표현식은 런타임이 아닌 번역 중에 평가 될 수 있으므로 상수가있는 모든 위치에서 사용할 수 있습니다.


for (i = 0; i <(1 << 7); i ++)

for (i = 0; i <128; i ++)

동일한 성능을 제공하지만 개발자는 for (i = 0; i <(1 << 7); i ++)가 루프에서 다음과 같이 사용되는 경우 큰 이점을 얻을 수 있습니다.

for(int k = 0; k < 8; k++)
{
  for(int i = 0; i < (1 << k); i++)
   {
    //your code
    }

}

이제 내부 루프 상한에 있습니다. 즉 (1 << k) 런타임의 거듭 제곱으로 변경됩니다. 그러나 알고리즘에이 논리가 필요한 경우 적용 할 수 있습니다.


컴파일러는 두 경우 모두 동일한 코드를 출력합니다. 컨텍스트에 따라 다른 형식을 사용하고 싶을 것입니다.

  1. 당신은 사용할 수 있습니다 NUM_STEPS또는 NUM_ELEMENTS_IN_NETWORK_PACKET그것은 일정한 부분이나 명확하게하려는 알고리즘의 설계 선택 때.
  2. 또는 , 상수 128임을 명확히하기 위해 작성할 수 있습니다 128.
  3. 또는 1 << 7경쟁에 참가하고 있고 테스트에서 "2 ^ 7 회 실행" 과 같은 내용이 표시되면 작성 하십시오 .

또는 비트 연산을 알고 있음을 과시 할 수 있습니다!

제 생각에 프로그래밍은 컴파일러와 그것을 읽어야 할 사람 두 사람에게 편지를 쓰는 것과 같습니다. 당신이 의미하는 바는 둘 다 명확해야합니다.


두 피연산자가 일정하기 때문에 전처리기에 의해 평가됩니다.

그러나 비트 시프트 대신 숫자를 사용하려는 경우 0x0100이어야하지 않습니까?

참고 URL : https://stackoverflow.com/questions/25582100/why-an-expression-instead-of-a-constant-in-ac-for-loops-conditional

반응형