간단히 말해서 (tl; dr) :
나는 OP의 코드에있는 주석을 약간 다르게 해석하고 있는데, 그들이 관찰했다고 주장하는 "더 나은 코드"는 실제 작업을 루프 "조건"으로 이동했기 때문이라고 생각합니다. 그러나 나는 그것이 매우 컴파일러에 특화되어 있고 그들이 만든 비교가 약간 다른 코드를 생성 할 수는 있지만 아래에서 볼 수 있듯이 대부분 무의미하고 아마도 쓸모가 없다는 것에 완전히 동의합니다.
세부:
do {} while
더 나은 코드를 생성하는 것에 대한 그의 코멘트에서 원저자가 의미 한 바를 말하기는 어렵지만 여기서 제기 된 것과는 다른 방향으로 추측하고 싶습니다. 우리는 루프 do {} while
와 while {}
루프 의 차이 가 매우 희박 하다고 믿습니다. Mystical은 말 했음),하지만이 코드에는 "더 재밌는"무언가가 있는데, 모든 작업을이 미친 상태에 넣고 내부 부분을 비워 둡니다 ( do {}
).
gcc 4.8.1 (-O3)에서 다음 코드를 시도했는데 흥미로운 차이점이 있습니다.
#include "stdio.h"
int main (){
char buf[10];
char *str = "hello";
char *src = str, *dst = buf;
char res;
do {
res = (*dst++ = *src++);
} while (res);
printf ("%s\n", buf);
src = str;
dst = buf;
do {
} while (*dst++ = *src++);
printf ("%s\n", buf);
return 0;
}
컴파일 후-
00000000004003f0 <main>:
...
; loop 1
400400: 48 89 ce mov %rcx,%rsi
400403: 48 83 c0 01 add $0x1,%rax
400407: 0f b6 50 ff movzbl 0xffffffffffffffff(%rax),%edx
40040b: 48 8d 4e 01 lea 0x1(%rsi),%rcx
40040f: 84 d2 test %dl,%dl
400411: 88 16 mov %dl,(%rsi)
400413: 75 eb jne 400400 <main+0x10>
...
;loop 2
400430: 48 83 c0 01 add $0x1,%rax
400434: 0f b6 48 ff movzbl 0xffffffffffffffff(%rax),%ecx
400438: 48 83 c2 01 add $0x1,%rdx
40043c: 84 c9 test %cl,%cl
40043e: 88 4a ff mov %cl,0xffffffffffffffff(%rdx)
400441: 75 ed jne 400430 <main+0x40>
...
따라서 첫 번째 루프는 7 개의 명령을 수행하고 두 번째 루프는 동일한 작업을 수행해야하지만 6 개의 명령을 수행합니다. 자, 나는 이것 뒤에 컴파일러 똑똑 함이 있는지 실제로 말할 수 없으며 아마도 우연 일뿐이지만이 프로젝트가 사용하는 다른 컴파일러 옵션과 어떻게 상호 작용하는지 확인하지 않았습니다.
반면 clang 3.3 (-O3)에서는 두 루프 모두 다음 5 개의 명령어 코드를 생성합니다.
400520: 8a 88 a0 06 40 00 mov 0x4006a0(%rax),%cl
400526: 88 4c 04 10 mov %cl,0x10(%rsp,%rax,1)
40052a: 48 ff c0 inc %rax
40052d: 48 83 f8 05 cmp $0x5,%rax
400531: 75 ed jne 400520 <main+0x20>
이는 컴파일러가 상당히 다르며 일부 프로그래머가 몇 년 전에 예상했던 것보다 훨씬 빠른 속도로 발전하고 있음을 보여줍니다. 또한이 댓글은 의미가없고 아직 이해가되는지 아무도 확인하지 않았기 때문에 아마 거기에있을 것입니다.
요점-가능한 최상의 코드로 최적화하고 싶다면 (그리고 그것이 어떻게 생겼는지 알고 있다면) 어셈블리에서 직접 수행하고 방정식에서 "중간자"(컴파일러)를 잘라내십시오. 그러나 그 최신 코드를 고려하십시오. 컴파일러와 최신 하드웨어는이 최적화를 쓸모 없게 만들 수 있습니다. 대부분의 경우 컴파일러가 해당 수준의 작업을 수행하도록하고 큰 작업을 최적화하는 데 집중하는 것이 훨씬 낫습니다.
해야 할 또 다른 요점-명령 수 (원래 OP 코드가 이후에 있었던 것으로 가정)는 결코 코드 효율성에 대한 좋은 측정이 아닙니다. 모든 명령어가 동일하게 생성 된 것은 아니며 일부 (예 : 간단한 reg-to-reg 이동)는 CPU에 의해 최적화되기 때문에 정말 저렴합니다. 다른 최적화는 실제로 CPU 내부 최적화를 손상시킬 수 있으므로 결국 적절한 벤치마킹 만 계산됩니다.