32

왜 이런가요?

 int x = 2;
    for (int y =2; y>0;y--){
        System.out.println(x + " "+ y + " ");
        x++;
    }

이것과 똑같이 인쇄됩니까?

 int x = 2;
        for (int y =2; y>0;--y){
            System.out.println(x + " "+ y + " ");
            x++;
        }

지금까지 내가 알고 있듯이 후행 증가는 처음에는 "그대로"사용되었습니다. 사전 증가가 먼저 추가 된 다음 사용됩니다. 이것이 for 루프의 본문에 적용되지 않는 이유는 무엇입니까?


  • (초기화, 조건, 증가) : 예. - Mitch Wheat
  • javap을 사용하여 둘 다에 대한 바이트 코드를 생성하고 참조하십시오. 실험 주의자가 되라. - duffymo

27 답변


56

루프는 다음과 같습니다.

int x = 2;
{
   int y = 2;
   while (y > 0)
   {
      System.out.println(x + " "+ y + " ");
      x++;
      y--; // or --y;
   }
}

이 코드를 읽으면 알 수 있듯이 for 루프의 세 번째 섹션에서 post 또는 pre decrement 연산자를 사용하는지 여부는 중요하지 않습니다.

보다 일반적으로 다음과 같은 형식의 for 루프가 있습니다.

for (ForInit ; Expression ; ForUpdate)
    forLoopBody();

while 루프와 정확히 같습니다 :

{
    ForInit;
    while (Expression) {
        forLoopBody();
        ForUpdate;
    }
}

for 루프는 좀더 콤팩트하므로 일반적인 관용구를 쉽게 파싱 할 수 있습니다.


  • 나는 이것이 오래되었다는 것을 알고 있지만, 나는 그들이 "동등"하다고 지적하고 싶었다. 왜냐하면 for 루프 예에서, "y" while 루프 예제와 함께 범위를 벗어나지 않고 루프 밖에서 선언되기 때문에 범위를 벗어납니다. - OhFiddleDiddle
  • @OhFiddleDiddle은 두 개의 동등한 것을 만들기 위해 여분의 괄호를 추가했습니다. - Paul Wagland

26

이러한 것들을 시각화하려면 for 루프를 while 루프로 확장하십시오.

for (int i = 0; i < 5; ++i) {
    do_stuff(i);
}

확장 대상 :

int i = 0;
while (i < 5) {
    do_stuff(i);
    ++i;
}

후행 증가 또는 앞선 증분을 루프 카운터에서 수행할지 여부는 중요하지 않습니다. 증분 표현식의 결과 (증가 전후의 값)가 동일한 명령문 내에서 사용되지 않기 때문입니다.


17

그것이 당신의 관심사 인 경우에 성과의 점에서 아무 다름도 없다. 오류가 발생할 때만 잘못 사용할 수 있습니다 (따라서 오류에 민감합니다).용도그것...동안증가분.

중히 여기다:

for (int i = 0; i < 3;)
   System.out.print(++i + ".."); //prints 1..2..3


for (int i = 0; i < 3;)
   System.out.print(i++ + ".."); //prints 0..1..2

또는

for (int i = 0; i++ < 3;)
   System.out.print(i + ".."); //prints 1..2..3


for (int i = 0; ++i < 3;)
   System.out.print(i + ".."); //prints 1..2

그러나 흥미로운 세부 사항은 일반적인 관용구가 사용한다는 것입니다.i++증분 표현에서for자바 컴파일러는 다음과 같이 컴파일한다.++i사용.


  • 그러나 그가 어떻게 사용했는지는 차이가 없습니다.++i또는i++수술은 단독으로 시행됩니다. - Powerlord
  • 사후 증가 연산자는 증가 후 사용 가능한 이전 값을 유지해야합니다. 두 번째 예가 필요합니다.0, 증분i기억하다0String 연결. - Ben S
  • +1. 결코 for-loop를 일반적인 코드의 약 3 줄로 생각하기 전에는 절대로 안됩니다. - Roman

13

++ i와 i ++는 int num = i ++ 및 int num = ++ i 또는 다른 표현식과 같은 대입 연산자와 함께 사용될 때 차이를 만듭니다. 위의 FOR 루프에서는 다른 표현식과 함께 사용되지 않으므로 증분 조건 만 있으므로 아무런 차이가 없습니다. 이 경우 i = i + 1을 의미합니다.


  • 13 upvotes? 그러나 그것은 잘못되었습니다! 아니대입 연산자와 함께 사용되는 경우 : 항상 표현식의 결과가 사용됩니다 (예 : 산술 비교 및 메소드 매개 변수). - fortran
  • @fortran : 질문은 FOR 루프에서 i ++ 또는 ++ i를 사용하는 것과 다른 점에 대해 질문합니다. 따라서 FOR 루프의 컨텍스트에서 둘 다 같은 의미입니다. 이 상황에서 내 대답이 잘못 되었다면 좀 더 설명해 주시겠습니까? - Sachin Shanbhag
  • for(int i = 0; i < 10; doSomething(i++))또는for(i = -1; ++i < 10;)사전 또는 사후 증가분과 함께 사용하면 실제로 차이가납니다 ... 그렇습니다. 귀하의 주장은for루프 (첫 번째 문장에서 컨텍스트를 지정하지 않았는지 다시 확인)가 잘못되었습니다. - fortran
  • @fortran : 내 대답을 편집했는데 현재의 질문 맥락에서 괜찮을까요? - Sachin Shanbhag

6

이 루프는 다음과 같습니다.while고리:

int i = 0;
while(i < 5)
{
     // LOOP
     i++; // Or ++i
}

그래서 예, 동일해야합니다.


  • 또는while(i++ < 5) - Nobody
  • @rmx :하지만 그렇지 않습니다.while(++i < 5)그리고 thats 요점 - Progman
  • @Progman :while(i++ < 5){...}~의 등가물이다.while(i < 5){i += 1;...}오히려for-동등한while(i < 5){...;i += 1;}? - Alan Plum

5

그 성명서는 그 자체에 있기 때문에. 증가 순서는 중요하지 않습니다.


4

이 두 경우는 increment 문이 완료된 후에 i 값이 비교되기 때문에 동일합니다. 그러나, 만약 당신이 그랬다면

if (i++ < 3) 

if (++i < 3)

당신은 사물의 순서에 대해 걱정해야 할 것입니다.

그리고 그랬다면

i = ++i + i++;

너는 그저 너트 야.


3

당신의 예제에는 아무 것도 없기 때문에~을 사용하여pre-increment 또는 post-increment로부터 반환 된 값. 포장을 시도하십시오System.out.println()주위의++xx++그 차이를보기 위해서.


3

로부터for 루프에 관한 Java 언어 스펙 장:

BasicForStatement :

    for ( ForInit ; Expression ; ForUpdate ) Statement

... ForUpdate 부분이있는 경우,   표현식은에서 평가됩니다.   왼쪽에서 오른쪽으로 순서;그들의   값이 있으면 버려집니다....   ForUpdate 부분이 없으면,   아무런 조치도 취하지 않습니다.

(하이라이트는 내 것입니다).


3

'for (초기; 비교; 증가)'항목의 '증가'항목이결과성명서의부작용이 경우에는 'i'가 증가하며 이는 두 경우 모두 동일합니다.


  • 너가 이것에 확장 할 수 있으면, 바위 것입니다. - Wolfpack'08
  • @Fohsap 그것은 나에게 분명하고 완전하게 보입니다. 그 중 어떤 부분을 이해하지 못 했습니까? - user207421

2

증분 인수가 평가되기 전에 검사가 수행됩니다. 'increment'연산은 처음에 선언되었지만 루프의 끝에서 수행됩니다.


2

다음 예제를 시도하십시오.

int i = 6;
System.out.println(i++);
System.out.println(i);

i = 10;
System.out.println(++i);
System.out.println(i);

당신은이 일에서 무엇을하는지 알아낼 수 있어야합니다.


1

가치는y~에서 계산됩니다.for진술과 가치x자체 회선에서 계산되지만System.out.println그들은 단지 참조됩니다.

네가 내부에서 감소했다면System.out.println, 당신은 다른 결과를 얻을 것이다.

System.out.println(y--);
System.out.println(--y);


1

여기에는 좋은 답변이 많이 있지만, 도움이 될 경우 :

y--와 --y를 부작용이있는 표현식 또는 표현식 뒤에 표현식으로 생각하십시오. y-- 이것과 같습니다 (이 예제들을 의사 어셈블리로 생각하십시오).

decrement y
return y

그리고 --y 이렇게 :

store y into t
decrement y
load t
return t

루프 예제에서는 반환 값을 어느쪽으로 든 버리고 부작용 만 사용합니다 (감소 확인 문이 실행 된 후 루프 확인이 수행되고 감소에 의해 반환 된 값을 받거나 확인하지 않음).


1

만약for표현식의 결과를 사용하는 루프i++또는++i무언가를 위해, 그것은 사실 일 것입니다, 그러나 그것은 사실이 아닙니다. 단지 부작용 때문입니다.

그런 이유로 당신은void거기에 숫자 표현식이 아니라 메소드가 있습니다.


0

증가분은 독립적 인 문장으로 실행됩니다. 그래서

그리고 ...;

- y;

서로 등가이며,

y = y - 1;


0

왜냐하면 이건:

int x = 2;
for (int y =2; y>0; y--){
    System.out.println(x + " "+ y + " ");
    x++;
}

효과적으로 컴파일러에 의해 다음과 같이 번역됩니다.

int x = 2;
int y = 2
while (y > 0){
    System.out.println(x + " "+ y + " ");
    x++;
    y--;
}

보시다시피,y--또는--y차이는 없습니다. 그래도 이렇게 루프를 작성하면 차이가 있습니다.

int x = 2;
for (int y = 3; --y > 0;){
    System.out.println(x + " "+ y + " ");
    x++;
}

이것은 루프의 두 변종과 동일한 결과를 산출하지만,--yy--여기에 당신의 프로그램이 망가질 것입니다.


0

그것은 맛의 문제입니다. 그들은 같은 일을합니다.

자바 클래스의 코드를 살펴보면 post-increment가있는 for 루프가 나타납니다.


  • 그들은 똑같은 짓을한다.표현식의 결과를 사용하지 않는 경우. - Michael Myers
  • @ mmyers : 당신이 옳습니다. 그러나 나는 그것을하는 코드를 결코 보지 못했습니다. (물론, 그것은 아닙니다.코드가 존재하지 않음). - Roman

0

귀하의 경우, 그것은 동일합니다, 전혀 차이가 없습니다.


0

당신 말이 맞아요. 차이점은 다음과 같습니다.

for(int i = 0; i < 5; )
       {
            System.out.println("i is : " + ++i);           
       }


0

예, 순차적으로 수행합니다. Intialisation, 평가 조건, 그리고 참이면 신체를 실행 한 다음 증분.

Prefix와 Postfix의 차이는 Increment / Decrement가있는 Assignment 작업을 수행 할 때만 나타납니다.


0

for "arguments"의 모든 부분은 분리 된 문장이므로 차이점은 없습니다.

그리고 흥미로운 점은 컴파일러가 단순한 사후 증분을 선행 증분으로 대체하기로 결정할 수 있으며 코드로 변경되지 않는다는 것입니다.


  • 나는 (똑똑한) 컴파일러가 게시물이나 사전 증분을 선택하지 않고 변수에 1을 더한다고 가정한다. (i += 1, INC 바이트 코드). 결과는 명령문에서 사용되지 않기 때문에. - Carlos Heuberger
  • 정확히 말하면 ByteCode는iinc그리고 그것은 대체 할 것이다.i++,++ii += 1. 컴파일러가 컴파일러에서 추출 할++i,i++모든 경우의 진술에서의 조작,simple iinc원래 진술 전후에 놓여있다. - Colin Hebert

0

그들은 똑같은 행동을하지 않습니다. 이 구조는나는 ++에 비해 약간 느리다.++ i왜냐하면 전자는 이전 값과 새로운 값을 모두 반환하기 때문입니다.나는. 반면에 후자는 이전 값인나는.

그렇다면 아마도 컴파일러는 약간의 마법을 수행하고 고립 된나는 ++~로++ i성능상의 이유로, 원시 알고리즘에 관해서는 엄격하게 동일하지는 않습니다.


  • 실적 주장이 귀하의for루프 사건? 내 생각 엔 대부분의 컴파일러가 i ++를 변경하기에 충분히 지성적이다. - Pin
  • 그들이하다굴다똑같다. 그들은 서로 다른 성능 특성을 나타낼 수 있지만, 그들의 행동은 동일합니다. - bruceboughton
  • Pin : 필자와 다른 많은 사람들이 대답에서 말한 것처럼 아마도 컴파일러는 접미사 증가 대신 접미사 증가를 바꿀 수 있습니다. - rewritten
  • 컴파일러는 그것을 간단하게 바꿀 것이다.INC바이트 코드i += 1. - Carlos Heuberger

0

Stackoverflow에는 비슷한 여러 게시물이 있습니다.

그러나 귀하의 질문은 모든 언어 또는 컴파일러에 특정한 것이 아니기 때문에 더 일반적인 것 같습니다. 위 질문의 대부분은 특정 언어 / 컴파일러를 다루고 있습니다.

다음은 요약입니다.

  • 우리가 C / C ++ / Java (아마 C #도)와 현대 컴파일러에 대해 이야기하고 있다면 :
    • 만약i정수 (const int,int, 등) :
      • 그러면 컴파일러는 기본적으로i++++i이는 의미 론적으로 동일하고 출력을 변경하지 않기 때문입니다. 이것은 생성 된 코드 / 바이트 코드를 검사하여 확인할 수 있습니다 (Java의 경우jclasslib 바이트 코드 뷰어).
    • 그밖에:
  • 그밖에:
    • 컴파일러가 의미 상 동일하다는 것을 보장 할 수 없기 때문에 모든 베팅은 꺼져 있으므로 최적화를 시도하지 않습니다.

따라서 C ++에서 클래스와 접미사 및 접두어 연산자를 재정의하면 (예 :std::iterator),이 최적화는 거의 수행되지 않습니다.

요약하자면:

  • 당신이 말하는 것을 의미하고, 당신이 의미하는 바를 말합니다. 증분 부분에 대한for루프를 사용하는 경우 거의 항상 프리픽스 버전 (예 :++i).
  • 사이의 컴파일러 switcheroo++ii++항상 할 수있는 것은 아니지만 가능한 경우 할 수 있도록 노력할 것입니다.


0

루프에서 첫 번째 초기화 후 조건 확인 후 해당 증분 / 감소 후에 실행합니다. 사전 / 증분 / 감소는 프로그램 코드에 영향을 미치지 않습니다.


0

+++ (post-incrementation) 대 ++ i (사전 증분) @me : "두 경우 모두 표현식이 평가되고 그 결과가 조건을 검사하는 데 사용됩니다. 사전 증가 사례에서 증가 expression은 변수를 증가시키고 결과 값을 반환합니다. 후행 증가의 경우 증분 표현식도 변수를 증가 시키지만 이전 값을 반환합니다. 결과적으로 사전 증가는 증가 된 값과 비교되지만 후행 증가는 두 경우 모두 조건이 점검 될 때 변수가 증가했습니다. " - tdammers


0

포스트와 사전 증가 연산자 사이에는 꽤 혼동이 있습니다. 이것은 Robert Sedgewick과 Kevin Wayne의 "알고리즘, 4 판"발췌에서 쉽게 이해할 수 있습니다.

증분 / 감소 연산자 : i ++는 i = i + 1과 같으며 값이 있습니다.   나는 식으로. 마찬가지로, i - i = i - 1과 동일합니다. 코드 ++ i와   - i는 표현식 값이 증가 / 감소 뒤에 취해진다는 점을 제외하면 동일합니다.   이전보다 감소.

예를 들면

x = 0; 
post increment:
x++;
step 1: 
assign the old value (0) value of the x back to x.So, here is x = 0.
step 2:
after assigning the old value of the x, increase the value of x by 1. So,
x = 1 now;

when try to print somthing like:
System.out.print(x++);
the result is x : 0. Because only step one is executed which is assigning 
old value of the x back and then print it.

But when, we do operation like this: 
i++;
System.out.print(i);
the result is x: 1. which is because of executing Step one at first 
statement and then step two at the second statement before printing  the 
value.

pre increment:
++x;
step 1: 
increase the value of x by 1. So, x = 1 now;
step 2:
assign the increased value back to x.

when try to print something like:
System.out.print(++1)  
the result is x : 1. Because the value of the x is raised by 1 and then 
printed. So, both steps are performed before print x value. Similarly, 
executing 
++i;
system.out.print(i);
Both steps are executed at statement one. At second statement, just the 
value of "i" is printed.

연결된 질문


관련된 질문

최근 질문