왜 i ++가 있습니까? 나는--; 서로 직후?


164

1997 년에 출시 된 nmap 의 소스 코드를 살펴 보니이 코드 섹션이 조금 이상해 보입니다.

int i=0, j=0,start,end;
char *expr = strdup(origexpr);
ports = safe_malloc(65536 * sizeof(short));
i++;                                         /* <<<<<< */
i--;                                         /* <<<<<< */
for(;j < exlen; j++) 
  if (expr[j] != ' ') expr[i++] = expr[j]; 
expr[i] = '\0';

왜 당신은 할 것이다 i++;다음 i--;바로 서로 후? i이며 0, 다음 i++회전 i1. 그 후, i--회전 i0.

원본 소스 코드에 연결하십시오. 검색 :

i++;
i--;

누구나 이것이 무엇인지 설명 할 수 있습니까?


25
저자 에게 물어보십시오 .
DaBler

8
나는 그들이 실험 또는 디버깅 코드의 일부라고 생각할 것입니다. 저자는 나중에 제거하는 것을 잊었습니다.
Nate Eldredge

6
그 이유는 분명히 당신을 혼란스럽게하는 것입니다. 그것이 유일한 목적입니다 :-) 이것이 고대 컴파일러의 일부 컴파일러 버그를 해결할 수있는 작은 기회가 있습니다.
gnasher729

18
@ RingØ : 재미를 위해 나는 godbolt : godbolt.org/z/yYyFrQ 에서 1988 년경 gcc 1.27로 시도했습니다 . (이것은 최신 시스템 헤더에서 작동하지 않으므로 모든 표준 라이브러리 함수를 직접 선언해야했습니다.) 그러나 -O실제로는 그 문을 최적화합니다.
Nate Eldredge

21
프로그래머가 라인을 통해 지불 한 것을 의미합니다.
TonyK

답변:


152

이것은 버그였습니다. 이 줄들은 함께i 바뀌지 않으므로 가 없었습니다.

nmap을 소개 한 링크 된 기사는 1997 년 9 월 1 일에 게시되었습니다. https://svn.nmap.org/nmap 에서 nmap의 SVN 저장소를 보면 1998 년 2 월 10 일에 체크인 한 초기 개정판에 해당 행이 없습니다.

int i=0, j=0,start,end;
char *expr = strdup(origexpr);
char *mem = expr;

ports = safe_malloc(65536 * sizeof(short));
for(;j < exlen; j++) 
  if (expr[j] != ' ') expr[i++] = expr[j]; 
expr[i] = '\0';

따라서 이것은 초기 nmap 소스 코드와 초기 체크인을 SVN에 게시하는 사이에 저자가 찾아서 고친 것입니다.


1
흠, 그 페이지 <pre>에도 기사 주변에 태그 가 없습니다 . 크롬의 관리자는 DOM의 건설 기간 동안 일부 문서 맹 글링을 어떻게 리드를 계시)
소행성 날개

4
의도하지 않은 독자들을 혼란스럽게합니다. 분명히 버그라고 말하고 싶습니다. ;-)
sergut

2
@sergut Wikipedia는 귀하의 의견에 동의하지 않지만, 이 블로그 게시물 은 동의합니다
Toivo Säwén

4
이제 iint가 아니고 연산자 오버로드가있는 멋진 클래스라면 부작용이있을 수 있습니다 (아마도 일반적으로 열악한 코딩 방법의 징후는 아니지만). (물론 이것이 C ++ 인 경우에만 적용됩니다.)
Darrel Hoffman

5
일부 컨텍스트 (메모리 매핑 된 IO)에서 변수를 변경하면 외부 영향을 미칠 수 있습니다.
nullromo

40

그건 소용 없어. 절대 아무것도하지 않습니다.

내가 추측한다면 아마도 개발 중에 사용 된 디버깅 코드의 일부 일 것입니다.

하나 i++또는 i--하나의 변경에 도입되었고 다른 하나는 다른 변경에 도입 되었다고 추측합니다 .

초기 소스 릴리스와 첫 번째 SVN 개정 사이에 개정 내역이 없기 때문에 소개 지점을 찾을 방법이 없습니다.


14
코드 디버깅에 대한 추측이 정확하다고 생각합니다. 나는 당신이 그것들을 기대하는 곳에서 중단 점을 얻기 위해 매우 다양한 종류의 디버깅 코드를 보았습니다.
Nathan Goings

9

비 최적화 컴파일러 또는 하드웨어 부작용을 인식하는 컴파일러의 경우 i ++; i-- 시퀀스는 for 루프를 통해 가져오고 중첩 된 if 경로에 관계없이 메모리에서 i를 읽은 다음 다시 쓰도록합니다.

병렬 처리에서는 코드 시퀀스가 ​​전역 복사본이 아닌 자체 로컬 변수 복사본을 사용하도록 컴파일러 해킹이 수행되기도합니다.

예제는 코드 스 니펫이므로 사용 된 컴파일러, 예상 운영 체제 / 하드웨어 또는 독립 스레드로 실행할 수있는 코드 시퀀스 / 기능인지 여부를 확인할 수 없습니다.

더 간단한 시스템에서는 디버깅 환경에서 트랩 기능을 사용하도록 변수 변경을 일시적으로 강제했습니다. 이 경우 개발이 완료되었을 때 작성자가 코드를 제거하는 것을 잊었을 수 있습니다.


1
그렇다면 왜 휘발성으로 선언하지 않습니까?
vsz

6
i지역 변수로서의 선언은 위의 코드에 나와 있으며 i++; i--행이 있는 지점에서 다른 스레드가 액세스 할 수있는 방법이 없습니다 .
인터 제이

@vsz 차라리 그가 의미 i하는 것은 비 휘발성이어야 한다는 것 입니다. 나는 C 또는 C ++의 스레딩을 다루지 않았으므로 어떻게 휘발성으로 취급 될 수 있는지와 그것을 어떻게 i++; i--억제 할 수 있는지에 대한 단서가 없습니다 .
Egor Hans

휘발성에는 스레드 안전성 외에도 다른 목적이 있습니다. 컴파일러가 최적화하지 않도록 디버깅하는 동안 사용할 수도 있습니다.
vsz

2

업데이트 된 코드 만 확인하시기 바랍니다. (i-1) 바로 다음에 (i = 2 + 1)을 사용하면 의미가 없습니다. i의 값은 변경되지 않습니다. c 또는 c ++ 컴파일러를 사용하여 시도 할 수 있습니다. 또는 다른 언어로도 동일합니다. 컴파일러에서 코드를 실행하여 내가 틀렸거나 옳은지 확인하고 틀린 대답을하는지 알려주십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.