C ++에서“->”연산자는 무엇입니까?


8924

읽고 나면 숨겨진 기능 및 C ++ / STL의 어두운 구석을comp.lang.c++.moderated, 나는 완전히 다음은 컴파일 및 Visual Studio 2008 및 G ++ 4.4 모두에서 일 니펫 것을 놀랐습니다.

코드는 다음과 같습니다.

#include <stdio.h>
int main()
{
    int x = 10;
    while (x --> 0) // x goes to 0
    {
        printf("%d ", x);
    }
}

산출:

9 8 7 6 5 4 3 2 1 0

GCC에서도 작동하기 때문에 이것이 C라고 가정합니다. 이것은 표준에서 어디에 정의되어 있으며 어디에서 왔습니까?


503
심지어 단지 적절한 간격 ... 나는 이제까지 변수 중 하나를 사이에 공백 본 적이 생각하지 않는다 ++또는 --이전 ...
매튜 Scharley

1154
이 "goes to"연산자는 되돌릴 수 있습니다 (0 <-x). 또한 "runs to"연산자 (0 <---- x)가 있습니다. Geez, 내가들은 가장 재미있는 것은 C ++ 구문 =) +1에 대해 들었습니다.
SadSido

233
재미있게도 해석은 매우 잘못되었지만 코드가 올바르게 수행하는 것을 설명합니다. :)
Noldorin

811
새로운 구문 가능성을 상상해보십시오 : #define upto ++<, #define downto -->. 당신이 악하다고 느끼면, 당신은 할 수 #define for while(있고 #define do ) {(그리고 #define done ;}) 쓸 수 for x downto 0 do printf("%d\n", x) done있고, 인류는 ...
Chris Lutz

98
완전히 새로운 표현 방식의 코딩 가능성을 열어 다음에 대한 몇 가지 컴파일러 경고를 희생 할 가치가 있습니다. bool CheckNegative (int x) {return x <0? 허위 사실 ); }
ttt

답변:


8600

-->연산자가 아닙니다. 그것은 사실 두 개의 분리 된 사업자에, --하고 >.

조건부 코드가 감소 하고 원래 값 (감소하지 않음) x을 반환 x한 다음 원래 값을 연산자 를 0사용하여 비교합니다 >.

이해를 돕기 위해 다음과 같이 진술을 작성할 수 있습니다.

while( (x--) > 0 )

262
다시 말하지만, 그것은 그 맥락에서 일종의 범위 연산자처럼 보입니다.
Charles Salvia

109
x가 0에 비해 다음 포스트 감소하고 있음을 말하는 것은 0과 비교 후 감소되는 말 X와 동일합니다
찰스 샐비어

8
나는 그것이 같지 않다고 생각합니다. "then"이라는 단어는 순서가 있음을 의미한다고 생각합니다 (포스트 감소 후 x의 값은 1보다 작습니다). "x를 줄인 다음 이전 값과 0을 비교하는 중"이라고 말할 수 있다고 생각합니다. 그러나 이것은 어쨌든 nitpicking입니다. 우리는 모두 무슨 뜻인지 알고 있습니다.
Johannes Schaub-litb

38
자바에서 그것은 또한 컴파일 :)
Steven Devijver

44
@Jay라는 이름은 잘못된 프로그래밍 스타일입니다. :-) 이것은 질문이 처음에 제기되었다는 사실에 의해 입증됩니다. 연산자를 관련이없는 것보다는 오퍼레이터에 텍스트로 묶는 것이 훨씬 더 합리적이므로 while (x-- > 0)더 적합 할 것입니다. 또한이 문제에 대한 괄호가 필요하지 않다는 것을 의미합니다 (적어도 고정 글꼴 편집기에서).
paxdiablo

3131

또는 완전히 다른 무언가를 x원한다면 ...로 슬라이드합니다 0.

while (x --\
            \
             \
              \
               > 0)
     printf("%d ", x);

수학적으로는 아니지만 모든 그림은 천 단어를 그립니다.


216
@mafutrct-내가 기억하는 것처럼 C에서 \는 줄 바꿈이없는 것처럼 다음 줄을 추가합니다. 여기서 \ s는 기본적으로 아무것도하지 않습니다.
Hogan

2
@mafu '\'문자는 현재 줄이 다음 줄에서 계속된다는 것을 컴파일러에게 알려주므로 컴파일러는 두 줄을 병합하여 하나로 컴파일해야합니다. x가 -1이 될 때까지 'while (x-> 0)'이 실행됩니다. 그러나 들여 쓰기를하는 방식은 x가 0으로 슬라이딩하는 것처럼 보입니다. '... X 슬라이드 0 동안'
Felype

16
IIRC, K & R C는 감소 연산자에서 '-'사이에 공백을 허용했습니다.이 경우 중간에 백 슬래시가있을 수있어 훨씬 더 시원해집니다. :)
Jules

10
@ArnavBorborah why waste words when a picture does a better job는이 문맥에서 농담으로 사용되는 오래된 표현 의미 입니다. (사실이 개 키워드가 whileprintf)
동기화

88
예, 모호한 슬라이드 연산자입니다. 어떻게 잊을 수 있을까!
demonkoryu


1277

그것은 동등하다

while (x-- > 0)

x--(포스트 감소)는 다음과 같습니다 x = x-1. 코드 는 다음과 같이 변환됩니다.

while(x > 0) {
    x = x-1;
    // logic
}
x--;   // The post decrement done when x <= 0

15
이것은 옳지 않습니다. 두 번째 경우 루프 바디 내부의 x 값이 다릅니다. 예제의 대 입문 은 논리 보다 위에 있어야합니다 . Postfix-1을 빼지 만 , 빼기 전의 값으로 비교가 이루어 집니다.
uliwitness

4
@uliwitness 이것들은 실제로 동일합니다. 접두사가 사용 된 0 >-- x경우에는 잘못 될 수 있습니다 .이 경우 x논리 전에 감소합니다. 후위에서는 논리가 감소 전에 실행되므로 두 샘플이 동일합니다. 자유롭게 작성하여 Console테스트하십시오.
Candleshark

12
그들은 여전히 ​​동등하지 않습니다. 첫 번째 루프 후 x는 -1 (또는 부호가없는 경우 오버플로 됨)이고 두 번째 루프 후에는 0입니다. (x가 음이 아닌 것으로 시작한다고 가정하면 루프가 x를 수정하거나 중단하지 않거나 ...)
Caesar

1
while(x=x-1,x+1 > 0)동일합니다.
SS Anne

2
@Shebham, 여기에 카운터 예제가 있습니다. x가 0으로 시작하면 원래 루프에서 -1로 종료되고 버전과 함께 0으로 유지됩니다. 그래서 그들은 동등하지 않습니다.
엘리엇

1208

x 반대 방향으로 더 빨리 0으로 갈 수 있습니다.

int x = 10;

while( 0 <---- x )
{
   printf("%d ", x);
}

8 6 4 2

화살표로 속도를 조절할 수 있습니다!

int x = 100;

while( 0 <-------------------- x )
{
   printf("%d ", x);
}

90 80 70 60 50 40 30 20 10

;)


6
어떤 운영 체제,이 유형의 출력 생성, 나는 오류 메시지가 있다는 우분투 12.04를 사용하고 있습니다
Bhuvanesh

74
명백하지만, C ++를 처음 접하는 모든 사람에게 이것을 읽으십시오. 둘 이상 증가 / 감소해야하는 경우에는 증가 된 할당을 사용하십시오.
Blimeo

263
"레이저"는 0입니다. while (0>-------------------- x) ... 동일한 출력.
Samuel Danielson

4
@phord 컴파일하지 않습니까? -> coliru.stacked-crooked.com/a/5aa89a65e3a86c98
doc

18
@doc c ++에서는 컴파일되지만 c에서는 컴파일되지 않습니다.
phord

548

이것의

#include <stdio.h>
int main(void){
     int x = 10;

     while( x-- > 0 ){ // x goes to 0

       printf("%d ", x);
     }

     return 0;
}

단지 공간 --만으로도 재미 있고 감소하고 >비교할 수 있습니다.


431

사용법 -->은 역사적으로 관련이 있습니다. 감소는 x86 아키텍처에서 증가하는 것보다 더 빠르며 (어떤 경우에도 여전히) 빠릅니다. 사용은 -->그 제안 x에가는 0수학적 배경을 가진 사람들에게, 그리고 호소.


479
사실이 아닙니다. 감소 및 증가는 동일한 시간이 걸리므로 이점은 0과 비교하는 것이 비교 대 변수에 비해 매우 빠르다는 것입니다. 이것은 x86뿐만 아니라 많은 아키텍처에서도 마찬가지입니다. JZ 명령어가있는 것 (0이면 점프) 주위를 파고 들면 비교에서 사이클을 절약하기 위해 뒤로 쓰여지는 많은 "for"루프를 찾을 수 있습니다. 이것은 변수를 감소시키는 행위가 제로 플래그를 적절히 설정함으로써 x86에서 특히 빠르므로 변수를 명시 적으로 비교하지 않고도 분기 할 수 있습니다.
burito

25
글쎄, 0으로 감소한다는 것은 루프 반복 당 0과 비교해야한다는 것을 의미하고 n을 반복하는 것은 각 반복마다 n을 비교하는 것을 의미합니다. 전자는 더 쉬워지는 경향이 있습니다 (일부 아키텍처에서는 모든 데이터 레지스터 작업 후에 자동으로 테스트됩니다).
Joey Adams

9
@burrito 동의하지 않지만, 0이 아닌 값으로 조절 된 루프는 일반적으로 거의 완벽하게 예측됩니다.
던컨

14
모든 플랫폼에서 (x86에서) 증가 및 감소가 동일하게 빠릅니다. 차이점은 루프 종료 조건을 테스트하는 것입니다. 카운터가 0에 도달했는지 확인하려면 실제로 여유 공간이 없습니다. 값을 줄이면 프로세서에 0 플래그가 설정되고 종료 조건을 감지하기 위해 해당 플래그 만 확인하면되지만 종료 조건 전에 비교 연산을 증가시켜야 할 때 감지 할 수 있습니다.
lego

7
물론 현대의 컴파일러는 루프를 자동으로 벡터화하고 반전시킬 수 있기 때문에 요즘은 그다지 좋지 않습니다.
Lambda Fairy

366
while( x-- > 0 )

그것이 파싱되는 방법입니다.


362

완전히 괴짜이지만, 이것을 사용할 것입니다 :

#define as ;while

int main(int argc, char* argv[])
{
    int n = atoi(argv[1]);
    do printf("n is %d\n", n) as ( n --> 0);
    return 0;
}


1
컴파일되지 않습니다. C는 Pascal이 아니며 내부 do ... while는 명령문 목록입니다. C에서는 블록이므로 반드시이어야합니다 do { ... } while.
user207421

25
@ EJP는 컴파일합니다. 구문은 do statement while ( expression ) ;입니다. 내가 말했듯이, 나는 그 예를 농담으로 이해했다는 것을 이해하기를 바랍니다.
Escualo

321

내가 읽은 한 권의 책 (나는 어느 책을 정확하게 기억하지 못한다)은 다음과 같이 말했다. 컴파일러 는 왼쪽 오른쪽 규칙을 사용하여 표현식을 가장 큰 토큰 으로 구문 분석하려고 시도합니다 .

이 경우 표현식은 다음과 같습니다.

x-->0

가장 큰 토큰으로 구문 분석 :

token 1: x
token 2: --
token 3: >
token 4: 0
conclude: x-- > 0

이 표현식에도 동일한 규칙이 적용됩니다.

a-----b

파싱 ​​후 :

token 1: a
token 2: --
token 3: --
token 4: -
token 5: b
conclude: (a--)-- - b

나는 이것이 복잡한 표현을 이해하는 데 도움이되기를 바랍니다 ^^


98
두 번째 설명이 올바르지 않습니다. 컴파일러는 lvalue를 반환하지 않기 때문에 컴파일 되지 않는를 보고 a-----b생각 합니다. (a--)-- - ba--
Tim Leaf

22
또한, x--두 개의 토큰입니다.
Roland Illig

23
@DoctorT : 어휘 분석기를 전달합니다. 시맨틱 패스 만 해당 오류를 해결할 수 있습니다. 그의 설명은 정확합니다.
v.oddou

9
당신 -->이 연산자 라고 생각 하는 한 (이것은 질문을함으로써 암시되는 것입니다),이 답변은 전혀 도움이되지 않습니다-토큰 2 -->만이 아니라고 생각할 것 --입니다. 이것이 -->연산자가 아니라는 것을 알고 있다면 질문의 코드를 이해하는 데 문제가 없을 것이므로 완전히 다른 질문이 없으면 이것이 어떻게 유용한 지 잘 모르겠습니다.
Bernhard Barker

4
@DoctorT 예제는 a후행 감소 연산자가 오버로드되어 lvalue를 반환 한다고 가정하면 정확할 수 있습니다 . coliru.stacked-crooked.com/a/e1effc351ae79e9f
doc


242

어쨌든, 우리는 지금 "가는"연산자가 있습니다. "-->"방향으로 기억하기 쉽고 "x가 0이되는 동안"은 의미가 있습니다.

또한 "for (x = 10; x > 0; x --)"일부 플랫폼 보다 약간 더 효율적 입니다.


17
특히 x의 값이 음수 일 때 항상 참이 될 수 없습니다.
Ganesh Gopalasubramanian

15
다른 버전은 같은 일을하지 않습니다- for (size_t x=10; x-->0; )루프의 본문은 9,8, .., 0으로 실행되지만 다른 버전은 10,9, .., 1을 갖습니다. 그렇지 않으면 부호없는 변수를 사용하여 루프를 0으로 끝내는 것이 까다 롭습니다.
피트 Kirkham

4
조금 오해의 소지가 있다고 생각합니다 ++>. 점진적인 작업을 수행하기 위해 다른 사람 이 필요 하기 때문에 문자 그대로 "가는"연산자가 없습니다 .
tslmy 2016 년

19
@Josh : 실제로 overflow는에 대해 정의되지 않은 동작을 제공 int하므로 x음수로 시작하면 개 를 0 으로 먹는 것처럼 쉽게 먹을 수 있습니다 .
SamB

3
@PeteKirkham에 의해 comnmet에 주어진 이유로 나에게 매우 중요한 관용구 0입니다. 서명되지 않은 양에 대해 루프를 줄이려고 할 때가 종종 있기 때문 입니다. (비교 while (n--)를 위해 unsigned 대신 쓰는 것과 같이 0에 대한 테스트 생략 관용구는 n아무것도 사지 않으며 나를 위해 가독성을 크게 저해합니다.) 또한 초기 색인보다 하나 이상 을 지정하는 유쾌한 속성이 있습니다. 원하는 (예를 들어, 배열을 통한 루프의 경우 크기를 지정) 나는 또한 -->공간이없는 것을 좋아하는데 , 이것은 관용구를 쉽게 인식 할 수있게하기 때문입니다.
Marc van Leeuwen

221

이 코드는 먼저 x와 0을 비교 한 다음 x를 줄입니다. (첫 번째 답변에서도 언급했습니다 : x를 후 감소시킨 다음 x와 0을 >연산자 와 비교합니다 .)이 코드의 출력을 참조하십시오.

9 8 7 6 5 4 3 2 1 0

먼저 출력에서 ​​0을 확인하여 비교 한 다음 감소시킵니다.

먼저 감소시키고 비교하려면 다음 코드를 사용하십시오.

#include <stdio.h>
int main(void)
{
    int x = 10;

    while( --x> 0 ) // x goes to 0
    {
        printf("%d ", x);
    }
    return 0;
}

출력은 다음과 같습니다.

9 8 7 6 5 4 3 2 1

177

이 코드를 실행하면 컴파일러에서 9876543210을 인쇄합니다.

#include <iostream>
int main()
{
    int x = 10;

    while( x --> 0 ) // x goes to 0
    {
        std::cout << x;
    }
}

예상대로. 는 while( x-- > 0 )사실을 의미합니다 while( x > 0). x--게시물을 감소시킵니다 x.

while( x > 0 ) 
{
    x--;
    std::cout << x;
}

같은 것을 쓰는 다른 방법입니다.

그래도 원본은 "x는 0에 가까워지는"것처럼 보입니다.


4
동일한 명령문에서 동일한 변수를 두 번 이상 증분 / 감소 할 때만 결과가 정의되지 않습니다. 이 상황에는 적용되지 않습니다.
Tim Leaf

13
while( x-- > 0 ) actually means while( x > 0)-나는 당신이 무엇을 말하려고했는지 확신하지 못하지만, 당신이 그것을 말한 방식 --은 그 의미 가 전혀 없다는 것을 의미합니다 .
Bernhard Barker

@Dukeling에서 포인트를 모으기 위해이 답변은 원래 게시물 과 동일하지 않습니다 . 원래 포스트에 x있을 것입니다 -1이 대답에,하면서, 루프 잎 후 x가 될 것입니다 0.
Mark Lakata

148

--와 사이에 공백이 없습니다 >. x사후 감소, 즉 조건을 확인한 후 감소합니다 x>0 ?.


42
공백이 없습니다. C (++)는 공백을 무시합니다.

27
@ H2CO3 이것은 사실이 아닙니다. 토큰을 구분하기 위해 공백을 사용해야하는 곳이 있습니다 (예 : in #define foo()및) #define foo ().
Jens

30
@Jens 방법 : "공백이 없습니다. C (++)는 불필요한 공백을 무시합니다."?
Kevin P. Rice

139

--는 IS 감량 운영자와 >는 IS 보다 큼 연산자.

두 연산자는 같은 단일 연산자로 적용됩니다 -->.


11
이들은 2 개의 개별 연산자로 적용 됩니다. 그들은 "단일 하나"처럼 보이기 위해 오도 하게 작성 되었습니다.
underscore_d

129

두 연산자의 조합입니다. 첫 번째 --는 값을 낮추기 >위한 것이며 값이 오른쪽 피연산자보다 큰지 확인하는 것입니다.

#include<stdio.h>

int main()
{
    int x = 10;

    while (x-- > 0)
        printf("%d ",x);

    return 0;
}

출력은 다음과 같습니다.

9 8 7 6 5 4 3 2 1 0            

122

실제로, x후 감소하고 그 상태를 점검하고 있습니다. 그것은 아닙니다 -->그것의,(x--) > 0

참고 : 값은 x사후 감소하므로 조건을 확인한 후에 변경됩니다. 다음과 같은 몇 가지 유사한 경우가 발생할 수도 있습니다.

-->    x-->0
++>    x++>0
-->=   x-->=0
++>=   x++>=0

6
++>는 while ()에서 거의 사용할 수 없습니다. "goes up to ..."연산자는 ++ <일 것입니다. 연산자->는 우연의 일치입니다.
Florian F

2
@ BenLeggiero 그것은 무언가를하는 코드를 생성한다는 의미에서 '작동'할 수 있지만 (가짜 똑똑한 코드를 좋아하지 않는 분노한 독자들) 사전 의미를 사용한다는 것은 의미가 다릅니다. 고안된 예로서, x1에서 시작 하면 루프 본문을 절대 실행하지 않지만 while ( (x--) > 0 )그렇게합니다. {edit} Eric Lippert는 C # 4 릴리스 정보 ( blogs.msdn.microsoft.com/ericlippert/2010/04/01/…)
underscore_d

120

CC ++ 는 "최대 뭉크"규칙을 따릅니다. a --- b가로 번역되는 것과 같은 방식으로 (a--) - b귀하의 경우로 x-->0번역됩니다 (x--)>0.

규칙에서 말하는 것은 기본적으로 왼쪽에서 오른쪽으로 갈 때 유효한 표현을 형성하는 최대 문자 수를 취함으로써 표현이 형성된다는 것입니다.


5
OP가 가정 한 것은 다음과 같습니다. "((a)->)"는 최대 뭉크였습니다. OP의 원래 가정이 잘못되었다는 것이 밝혀졌습니다. "->"는 최대 유효한 연산자가 아닙니다.
david

4
내가 올바르게 기억한다면 탐욕스러운 파싱이라고도합니다.
Roy Tinker

1
@RoyTinker Greedy 스캐닝. 파서는 이것과 아무 관련이 없습니다.
user207421

27

왜 모든 합병증?

원래 질문에 대한 간단한 답변은 다음과 같습니다.

#include <stdio.h>
int main()
{
    int x = 10;
    while (x > 0) 
    {
        printf("%d ", x);
        x = x-1;
    }
}

같은 일을합니다. 당신이 이렇게해야한다고 말하지는 않지만 같은 일을하고 한 게시물에서 질문에 대답했을 것입니다.

x--상기 단지 속기이고, >단지 정상보다 큰 것이다 operator. 큰 수수께끼가 없습니다!

요즘 간단한 일을 복잡하게 만드는 사람들이 너무 많습니다.)


17
이 질문은 복잡한 문제가 아니라 ** C ++ / STL의 숨겨진 기능과 어두운 부분 **에 관한 것입니다.
pix

20
여기의 x는 printf 후에 감소하므로 여기의 프로그램은 원본과 다른 출력을 제공합니다. 그것은 "간단한 대답"이 일반적으로 어떻게 부 정확한지를 잘 보여줍니다.
Öö Tiib

2
The OP's way: 9 8 7 6 5 4 3 2 1 0The Garry_G way: 10 9 8 7 6 5 4 3 2 1
안토니

2
그것은 같은 일을하지 않습니다. 당신을 이동 x=x-1하기 전에 printf당신은 "이 같은 일을"말할 수있는 다음.
CITBL

26

일반적인 방식으로 while루프 괄호 안에 조건을 정의 ()하고 중괄호 안에 종료 조건을 정의 {}하지만 -->한 번에 두 가지를 모두 정의합니다.

예를 들면 다음과 같습니다.

int abc(void)
{
    int a = 5
    while((a--) > 0) // Decrement and comparison both at once
    {
        // Code
    }
}

이보다 큰 a루프는 감소 하고 루프를 실행합니다 .a0

일반적으로 다음과 같습니다.

int abc(void)
{
    int a = 5;
    while(a > 0)
    {
        a--;
        // Code
    }
    a--;
}

두 가지 방법으로, 우리는 같은 일을하고 같은 목표를 달성합니다.


5
이것은 올바르지 않습니다. 질문의 코드는 'test-write-execute'(먼저 테스트하고 새 값을 쓰고 루프를 실행)합니다. 예는 'test-execute-write'입니다.
v010dya

@ v010dya 답을 고쳤습니다. 이제 test-write-execute질문 에서 와 같이 지적 해 주셔서 감사합니다!
Kotauskas

@VladislavToncharov 편집 내용이 여전히 잘못되었습니다. 내 참조하십시오.
SS Anne

8

(x --> 0) 방법 (x-- > 0)

  1. 당신이 사용할 수있는 (x -->)
    output -: 9 8 7 6 5 4 3 2 1 0

  2. 당신은 (-- x > 0) 그것을 사용할 수 있습니다(--x > 0)
    output -: 9 8 7 6 5 4 3 2 1

  3. 당신이 사용할 수있는
(--\
    \
     x > 0)

output -: 9 8 7 6 5 4 3 2 1

  1. 당신이 사용할 수있는
(\
  \
   x --> 0)

output -: 9 8 7 6 5 4 3 2 1 0

  1. 당신이 사용할 수있는
(\
  \
   x --> 0
          \
           \
            )

output -: 9 8 7 6 5 4 3 2 1 0

  1. 당신은 또한 사용할 수 있습니다
(
 x 
  --> 
      0
       )

output -: 9 8 7 6 5 4 3 2 1 0

마찬가지로이 명령을 성공적으로 실행하기 위해 많은 방법을 시도 할 수 있습니다

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