"x = x ++"다음에 x는 무엇입니까?


285

이것이 실행될 때 (커튼 뒤) 어떻게됩니까?

int x = 7;
x = x++;

즉, 변수가 포스트 증분되어 하나의 명령문으로 자체에 할당되는 경우입니다. 나는 이것을 컴파일하고 실행했다. 전체 진술 후에도x 여전히 7 입니다. 내 책에는 그것이 증가 한다고 말합니다 !x


9
시도해보십시오 : int x = 7; x = ++x;물론 여전히 끔찍한 코드이므로 다시 할당 할 필요가 없습니다. int x = 7; x++;충분하다.
stivlo

7
이것은 실제로 나쁜 습관입니다. 사용하는 줄과 같은 줄에서 변수를 늘리지 마십시오.
Yousf

5
x += 1루프를 제외하고는 을 사용하고 싶습니다 . for(int x=0; x<7; x++)
Svish

2
@andyortlieb 객체가 없으며 기본 값입니다.
포트란

답변:


301

x증가합니다. 그러나 당신은 이전의 가치를 x다시 부여하고 있습니다.


x = x++;
  1. x++증가 x하고 이전 값을 반환합니다.
  2. x = 이전 값을 다시 자신에게 할당합니다.

결국, x초기 값으로 다시 할당됩니다.


3
그러면 x = ++ x에 대해 무엇을 말할 것입니까;
Hisham Muneer

3
이 경우 @HishamMuneer를 x읽기 전에 먼저 증가하므로으로 끝납니다 x + 1.

@HishamMuneer 너무 늦었다. 그러나 앞으로 볼 다른 사람들에게 도움이 될 수 있기 때문에 여기에 넣었습니다. 이 문제를 이해하는 가장 좋은 방법은 x = x ++ 및 x = ++ x 용으로 작성된 어셈블리 코드를 보는 것입니다. Thinkingcap의 답변도 참조하십시오.
nantitv

나는 이것이 매우 오래되었다는 것을 알고 있지만 질문이 있습니다. 위의 작동 순서는 표준에 의해 보장됩니까? 증분 전에 할당을 실행할 수 있습니까?
에메랄드 무기

@EmeraldWeapon 그것은 자바로 정의됩니다. 그것은 단지 C / C ++에만 있습니다.
Mysticial

385
x = x++;

에 해당

int tmp = x;
x++;
x = tmp;

46
재귀 적 정의를위한 롤. 당신은 아마 x=x+1대신 해야했을 것 입니다x++
user606723

8
@ user606723 : 아니요 . x = x++포스트 증가가 아니라 전체 문장을 의미했습니다 x++.
프린스 존 웨슬리

20
나는 이것이 더 이상의 설명없이 유용한 것이라고 생각하지 않습니다. 예를 들어,에 해당하는 x = ++x;것은 사실이 int tmp = x; ++x; x = tmp;아니므로 어떤 논리에 의해 귀하의 답변이 정확하다고 판단 할 수 있습니까?
kvb

4
더 명확하다 asm x=x++ =MOV x,tmp; INC x; MOV tmp,x
forker

3
@forker : Michael이 사용하는 프로세서에 적용되는 조립 지침을 사용하면 더 명확 할 것입니다.)
Carl

258

진술 :

x = x++;

다음과 같습니다.

tmp = x;   // ... this is capturing the value of "x++"
x = x + 1; // ... this is the effect of the increment operation in "x++" which
           //     happens after the value is captured.
x = tmp;   // ... this is the effect of assignment operation which is
           //     (unfortunately) clobbering the incremented value.

요컨대, 그 진술은 효력이 없다.

요점 :

  • Postfix 증가 / 감소 표현식의 값은 증가 / 감소가 발생 하기 전의 피연산자 값입니다 . (접두사 양식의 경우 값은 연산 피연산자의 값입니다. )

  • 값이 LHS에 할당 되기 전에 할당 표현식의 RHS가 완전히 평가됩니다 (증가, 감소 및 / 또는 기타 부작용 포함) .

C 및 C ++와 달리 Java의 표현식 평가 순서는 완전히 지정되며 플랫폼 별 변형의 여지가 없습니다. 컴파일러는 현재 스레드의 관점에서 코드 실행 결과를 변경하지 않는 경우에만 작업 순서를 다시 지정할 수 있습니다. 이 경우 컴파일러는 명령문이 작동하지 않음을 증명할 수 있으므로 전체 명령문을 최적화 할 수 있습니다.


아직 명확하지 않은 경우 :

  • "x = x ++;" 거의 모든 프로그램에서 실수입니다.
  • OP (원래 질문에 대한)는 아마도 "x ++;"를 의미했을 것입니다. "x = x ++;"대신.
  • 같은 변수에 대한 자동 증가 / 감소와 할당을 결합한 문장은 이해하기 어렵 기 때문에 정확성에 관계없이 피해야 합니다 . 그런 코드를 작성할 필요는 없습니다.

다행히 FindBugs 및 PMD와 같은 코드 검사기는 이와 같은 코드를 의심스러운 것으로 플래그 지정합니다.


7
부수적으로 OP는 아마도 x++대신 대신 말하는 것을 의미합니다 x = x++.
Jon Newmuis

3
맞지만, 증가는 오른손 식 평가 이후에 발생 하지만 왼쪽에 사전 할당되어 발생한다는 점을 강조합니다. 따라서 명백한 "덮어 쓰기"
보헤미안

2
그것은 고등학교 프로그래밍 트위스터 중 하나 인 것 같습니다 ... 기본을 정리하는 것이 좋습니다!
kumarharsh

1
@Alberto- "전문가"진술을 "복음 진리"로 받아들이지 않는다는 말을 듣는 것이 좋습니다. 그러나 내가 말한 것을 검증하는 더 좋은 방법은 JLS에 문의하는 것입니다. 컴파일 / 디 컴파일 테스트는 내가 말한 것이 하나의 Java 컴파일러에 대해서만 유효하다는 것을 보여줍니다. JLS가 허용하지 않는 것을 제외하고 다른 사람들은 (가설 적으로) 다르게 행동 할 수 있습니다.
Stephen C

4
참고로, 이것은 원래 다른 질문에 게시되었으며이 질문의 복제본으로 닫히고 이제 병합되었습니다.
Shog9

33
int x = 7;
x = x++;

C에서는 동작이 정의되어 있지 않으며 Java의 경우이 답변을 참조하십시오 . 컴파일러에 따라 달라집니다.


4
아니오 그것은 당신이 인용 한 답변에 따라 컴파일러에 의존하지 않습니다-지금 편집하십시오
--1

@Mr_and_Mrs_D 그렇다면 그것은 무엇에 달려 있습니까?
Mac

2
C_에 대해서는 정의되지 않은 behavior_only입니다. 그럼에도 불구하고 컴파일러에 의존한다고 말하는 것은 오해의 소지가 있습니다. 컴파일러 가이 동작을 지정해야 함을 의미합니다. 투표를 되돌
리지만

16

다음과 같은 구조 x = x++;++운영자가 수행 하는 작업을 오해하고 있음을 나타냅니다 .

// original code
int x = 7;
x = x++;

++연산자 를 제거하여 동일한 작업을 수행하도록 이것을 다시 작성해 보겠습니다 .

// behaves the same as the original code
int x = 7;
int tmp = x; // value of tmp here is 7
x = x + 1; // x temporarily equals 8 (this is the evaluation of ++)
x = tmp; // oops! we overwrote y with 7

자, 당신이 원했던대로 (내 생각에) 다시 작성해 봅시다.

// original code
int x = 7;
x++;

여기서 미묘한 점은 ++연산자 xx + x int 값으로 평가되지만 변수 x자체는 변경되지 않은 상태 와 같은 식과 달리 변수를 수정한다는 것 입니다. 훌륭한 for루프 와 같은 구성을 고려하십시오 .

for(int i = 0; i < 10; i++)
{
    System.out.println(i);
}

i++거기에 주목 ? 같은 연산자입니다. 이 for루프를 다음과 같이 다시 작성할 수 있으며 동일한 동작을합니다.

for(int i = 0; i < 10; i = i + 1)
{
    System.out.println(i);
}

또한 ++대부분의 경우 연산자를 더 큰 식으로 사용하지 않는 것이 좋습니다 . 사전 및 사후 증분 ( 및) 에서 원래 변수를 수정할 의 미묘함 때문에 추적하기 어려운 미묘한 버그를 쉽게 도입 할 수 있습니다.++xx++


13

클래스 파일에서 얻은 바이트 코드에 따르면

두 할당 모두 x를 증가 시키지만 차이는 when the value is pushed onto the stack

에서 Case1, 증가 이전에 푸시가 발생했다가 나중에 할당됩니다.

Case2에서 증가가 먼저 발생 하여 (8) 스택에 푸시 된 다음 x에 할당됩니다.

사례 1 :

int x=7;
x=x++;

바이트 코드 :

0  bipush 7     //Push 7 onto  stack
2  istore_1 [x] //Pop  7 and store in x
3  iload_1  [x] //Push 7 onto stack
4  iinc 1 1 [x] //Increment x by 1 (x=8)
7  istore_1 [x] //Pop 7 and store in x
8  return       //x now has 7

사례 2 :

int x=7; 
x=++x;

바이트 코드

0  bipush 7     //Push 7 onto stack
2  istore_1 [x] //Pop 7 and store in x
3  iinc 1 1 [x] //Increment x by 1 (x=8)
6  iload_1  [x] //Push x onto stack
7  istore_1 [x] //Pop 8 and store in x
8  return       //x now has 8
  • 여기서 스택은 피연산자 스택, 로컬 : x 인덱스 : 1 유형 : int를 나타냅니다.

답변을 자세히 설명해 주시겠습니까?
Nihar

Pls는 참조 링크와 의견을
보아라

8

" x = x++;" 다음에 증가 합니다. " x = ++x;"를 수행 하면 8이됩니다 .


4
이 후에 증가되는 경우 x = x++, 그것은 제되어야
R. 마르틴 페르난데스

8

사후 증가 연산자는 다음과 같이 작동합니다.

  1. 피연산자의 이전 값을 저장하십시오.
  2. 피연산자의 값을 증가시킵니다.
  3. 피연산자의 이전 값을 반환합니다.

그래서 진술

int x = 7;
x = x++; 

다음과 같이 평가됩니다.

  1. x는 값 7로 초기화됩니다
  2. 후행 증가 연산자는 x의 이전 값, 즉 7을 저장합니다.
  3. x를 증가 시키므로 이제 x는 8입니다
  4. x의 이전 값 7을 반환하고 다시 x에 할당되므로 x는 다시 7이됩니다.

따라서 x는 실제로 증가하지만 x ++는 결과를 x에 다시 할당하므로 x의 값은 이전 값으로 재정의됩니다.


그러나 msvc x에서 8은 gcc와 clang x에서 7입니다.
Summer Sun

7

x가 호출 된 후에 증가가 발생하므로 x는 여전히 7과 같습니다. x가 호출 될 때 ++ x는 8과 같습니다.


7

값을 다시 할당 x해도 여전히 7입니다. 시도 x = ++x하면 8이됩니다.

x++; // don't re-assign, just increment
System.out.println(x); // prints 8

6

x ++는 변수에 값을 할당 한 후 값을 증가시키기 때문입니다. 그래서이 줄을 실행하는 동안 :

x++;

varialbe x는 여전히 원래 값 (7)을 가지지 만 다른 행에서 x를 다시 사용합니다 (예 :

System.out.println(x + "");

당신에게 줄 것이다 8.

과제 명세서에 증분 된 x 값을 사용하려면

++x;

이것은 x를 1 씩 증가시키고, 그 값을 변수 x에 할당합니다.

x = x ++ 대신 [편집], 그것은 단지 x ++입니다; 전자는 x의 원래 값을 자신에게 할당하므로 실제로 해당 줄에 아무것도 수행하지 않습니다.


할당 후 증가한다고 말하고, 인쇄하면 8이라고 인쇄합니다. 할당하기 전에 증가하고 7을 인쇄합니다.
R. Martinho Fernandes

x가 원래 7이면 System.out.println (String.valueOf (x ++)); 인쇄 7. 동일한 프로그래밍 언어에 대해 이야기하고 있습니까?
josephus

네 이 ideone.com/kj2UU 는이 답변 주장과 같이 8을 인쇄하지 않습니다.
R. Martinho Fernandes '12

예, 틀 렸습니다. x = x ++는 x를 증가시키기 전에 7을 x에 먼저 할당합니다. x ++ (자체 할당)는 x = (무엇이든) 전에 먼저 해결되므로 x = (무엇이든)에서 x에 할당 된 값이 뒤 따릅니다. 미안 나는 그것을 보지 못했다.
josephus

1
실제로 증분이 가장 먼저 발생합니다. ideone.com/xOIDU
R. Martinho Fernandes

4

언제 발생 int x = 7; x = x++;합니까?

ans-> x++는 먼저 표현식에 x 값을 사용한 다음 1 씩 증가시키는 것을 의미합니다.
이것은 귀하의 경우에 발생합니다. RHS의 x 값은 LHS의 변수 x에 복사 된 다음 x1의 값 이 증가합니다.

마찬가지로 x의 값을 먼저 증가시킨 다음 expression에 사용하는 ++x 것을 의미 ->합니다.
따라서 귀하의 경우 x = ++x ; // where x = 7
에는 8의 가치를 얻습니다.

더 명확하게 보려면 다음 코드를 실행할 printf 문 수를 찾으십시오.

while(i++ <5)   
  printf("%d" , ++i);   // This might clear your concept upto  great extend

맞지 않음 "RHS의 x 값이 LHS의 변수 x에 복사 된 다음 x의 값이 1 씩 증가합니다."- x8이되지만 7과
같음

3

++x사전 증분 ->x는 사용 전에 증분 되고
x++사후 증분 ->x는 사용 증분 됩니다

int x = 7; -> x get 7 value <br>
x = x++; -> x get x value AND only then x is incremented

1

따라서 이것은 다음 x++과 같습니다.x = x+1

때문에:

int x = 7; x = x++;
x is 7

int x = 7; x = x = x+1;
x is 8

이제는 조금 이상해 보입니다.

int x = 7; x = x+=1;
x is 8

매우 컴파일러에 의존합니다!


2
누가 처음부터 평등하다고 했습니까?
포트란

1
내가 당신이라면 나는이 책들을 즉시 버릴 것입니다. xD 어쨌든, (x = x + 1, x-1)쉼표로 구분 된 표현이 허용되는 C 와 같습니다 .
포트란

3
@fortran : 글쎄요, 159 페이지의 "The Java Programming Language, Third Edition"의 10 년 전 사본에서 "i ++ 식은 i = i + 1과 동일합니다. ? 처음 제임스 고슬링 (James Gosling)에, 그것은 나타납니다 자바 스펙이 버전의이 부분은 매우 모호하고 불완전 지정이며, 나중에 판 더 명확 실제 운영자의 의미를 표현하는 언어를 청소 것으로 추정..
에릭 Lippert의

2
@fortran : "i는 한 번만 평가된다"는 기준에 의해 표준은 "M (). x ++"와 같은 표현식이 M ()을 한 번만 호출한다는 것을 전달하려고합니다. 덜 모호하고보다 정확한 표현은 차이가 있음을 강조 할 의 저장 위치를 결정하는 변수로 난을 평가하는 것을 여기에 "한 번만 평가"의 의미입니다 - - 그리고 읽기 또는 저장 위치에 쓰기가 - - '평가 된'에 대한 합리적이지만 부정확 한 해석 일 수 있습니다. 저장 위치는 반드시 읽고 쓸 수 있어야합니다!
Eric Lippert

1
"매우 컴파일러에 따라 다름" -전혀 아닙니다!
Stephen C

-1

x = x ++;

이것은 증분 후 연산자입니다. "피연산자의 값을 사용한 다음 피연산자를 증가 시키십시오"로 이해해야합니다.

"피연산자를 증가시킨 다음 피연산자 값을 사용하십시오"와 같은 역전이 발생하도록하려면 아래 그림과 같이 사전 증가 연산자를 사용해야합니다.

x = ++ x;

이 연산자는 먼저 x의 값을 1 씩 증가시킨 다음 x에 다시 값을 할당합니다.


-1

이 논쟁은 코드에 들어 가지 않고 그냥 생각하지 않고도 해결할 수 있다고 생각합니다.

Func1 & Func2와 같이 i ++ & ++ i를 함수로 생각하십시오.

이제 i = 7;
Func1 (i ++)은 7을 반환하고 Func2 (++ i)는 8을 반환합니다 (모두 알고 있음). 내부적으로 두 함수 모두 i ~ 8을 증가 시키지만 다른 값을 반환합니다.

따라서 i = i ++는 Func1 함수를 호출합니다. 함수 내에서 i는 8로 증가하지만 완료되면 함수는 7을 반환합니다.

따라서 궁극적으로 7은 i에 할당됩니다. (결국 i = 7)


2
여기에는 유효한 "논쟁"이 없습니다. 코드 는 특정 방식으로 명백하게 작동하며 동작은 JLS를 따릅니다. 다르게 행동한다고 ​​생각하는 사람은 시도하지 않았거나 대담하게 행동합니다. (이것은 누군가가 시간표를 잊었을 때 7 x 7 is 49가 "논란의 여지가 많다"고 말하는 것과 약간 비슷합니다.)
Stephen C

-2

사후 증가 연산자를 사용했기 때문입니다. 다음 코드 줄에서

x = x++;

x의 값을 x에 할당하는 것입니다. x의 값이 x에 할당 된 후 x ++는 x를 증가시킵니다. 이것이 증분 후 연산자의 작동 방식입니다. 명령문이 실행 된 후에 작동합니다. 따라서 코드에서 x가 먼저 반환 된 다음 나중에 증가합니다.

네가했다면

x = ++x;

사전 증분 연산자를 사용했기 때문에 대답은 8입니다. x 값을 반환하기 전에 먼저 값을 증가시킵니다.

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