IT이야기

C for-loop의 조건에서는 왜 상수 대신 식을 사용하는가?

cyworld 2022. 6. 14. 22:43
반응형

C for-loop의 조건에서는 왜 상수 대신 식을 사용하는가?

많은 프로그래밍 대회에서 나는 사람들이 이런 종류의 글을 쓰는 것을 보았다.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++)

그리고.

(i = 0, i < 128, i++)의 경우

(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)는 2 런타임의 거듭제곱으로 변화합니다.단, 알고리즘에 이 논리가 필요한 경우에는 적용할 수 있습니다.

컴파일러는 양쪽 케이스에서 같은 코드를 출력합니다.상황에 따라 다른 형식을 사용하는 것이 좋습니다.

  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-a-c-for-loops-conditional

반응형