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 런타임의 거듭제곱으로 변화합니다.단, 알고리즘에 이 논리가 필요한 경우에는 적용할 수 있습니다.
컴파일러는 양쪽 케이스에서 같은 코드를 출력합니다.상황에 따라 다른 형식을 사용하는 것이 좋습니다.
- 하시면 됩니다.
NUM_STEPS
★★★★★★★★★★★★★★★★★」NUM_ELEMENTS_IN_NETWORK_PACKET
알고리즘에서 일정 부분 또는 설계 선택을 명확히 하고 싶은 경우. - 이렇게 쓸 도 있어요.
128
실실하 , , , , , , , , , , , , , ,.128
, , , , , 수수. - ㅇㅇㅇㅇㅇ라고 적습니다.
1 << 7
'2^7번 뛰어요' 이런 거 있잖아요.
또는 비트 조작을 알고 있다고 뽐낼 수도 있습니다.
저의 겸손한 의견으로는, 프로그래밍은 두 사람에게 편지를 쓰는 것과 같습니다. 컴파일러와 그것을 읽어야 할 사람입니다.두 사람 모두 무슨 뜻인지 분명해야 합니다.
양쪽 오퍼랜드가 일정하기 때문에 프리프로세서에 의해 평가됩니다.
하지만 비트 시프트 대신 숫자를 사용한다면 0x0100이 되어야 하지 않을까요?
언급URL : https://stackoverflow.com/questions/25582100/why-an-expression-instead-of-a-constant-in-a-c-for-loops-conditional
'IT이야기' 카테고리의 다른 글
Vuex 동적 확인란 바인딩 (0) | 2022.06.15 |
---|---|
vuex 작업 및 jsdoc: 주입된 함수 매개 변수를 표시하는 방법 (0) | 2022.06.14 |
chartData 치환, 갱신 시 vue.js vue-chartjs 차트가 갱신되지 않음 (0) | 2022.06.14 |
구성 요소를 기존 Vue.js 인스턴스에 등록합니다. (0) | 2022.06.14 |
IntelliJ: 와일드카드 Import 사용 안 함 (0) | 2022.06.14 |