Programing

i = (i, ++ i, 1) + 1은 무엇입니까?

crosscheck 2020. 5. 22. 23:46
반응형

i = (i, ++ i, 1) + 1은 무엇입니까? 하다?


정의되지 않은 동작 및 시퀀스 포인트에 대한 이 답변을 읽은 후 작은 프로그램을 작성했습니다.

#include <stdio.h>

int main(void) {
  int i = 5;
  i = (i, ++i, 1) + 1;
  printf("%d\n", i);
  return 0;
}

출력은 2입니다. 오 하나님, 나는 감소가 오는 것을 보지 못했습니다! 여기서 무슨 일이 일어나고 있습니까?

또한 위의 코드를 컴파일하는 동안 경고 메시지가 나타납니다.

px.c : 5 : 8 : 경고 : 쉼표 식의 왼쪽 피연산자는 효과가 없습니다.

  [-Wunused-value]   i = (i, ++i, 1) + 1;
                        ^

왜? 그러나 아마도 첫 번째 질문에 대한 답변으로 자동 응답 될 것입니다.


식에서 (i, ++i, 1)쉼표는 쉼표 연산자입니다.

쉼표 연산자 (token으로 ,표시됨)는 첫 번째 피연산자를 평가하고 결과를 버린 다음 두 번째 피연산자를 평가하여이 값 (및 유형)을 리턴하는 2 진 연산자입니다.

첫 번째 피연산자가 삭제되므로 일반적으로 첫 번째 피연산자가 바람직한 부작용을 갖는 경우에만 유용합니다 . 첫 번째 피연산자에 대한 부작용이 발생하지 않으면 컴파일러는 아무런 영향없이 표현식에 대한 경고를 생성 할 수 있습니다.

따라서 위의 식에서 가장 왼쪽 i이 평가되고 해당 값이 삭제됩니다. 그런 다음 ++i평가 i되고 1 씩 증가 하고 표현식의 값은 ++i무시 되지만 부작용 i은 영구적 입니다. 그런 다음 1평가되고 표현식의 값은입니다 1.

그것은

i;          // Evaluate i and discard its value. This has no effect.
++i;        // Evaluate i and increment it by 1 and discard the value of expression ++i
i = 1 + 1;  

참고 상기 식 완벽 유효하고 정의되지 않은 동작 호출하지 않는 있기 때문에 순서 포인트 콤마 연산자의 좌우 피연산자의 평가 사이가.


C11, 챕터 6.5.17, 쉼표 연산자 인용

쉼표 연산자의 왼쪽 피연산자는 void 표현식으로 평가됩니다. 평가와 올바른 피연산자의 평가 사이에는 순서 점이 있습니다. 그런 다음 올바른 피연산자가 평가됩니다. 결과 유형과 값이 있습니다.

따라서 귀하의 경우에는

(i, ++i, 1)

로 평가된다

  1. i, void 표현식으로 평가되고 값이 삭제됩니다.
  2. ++i, void 표현식으로 평가되고 값이 삭제됩니다.
  3. 마지막으로 1값이 반환되었습니다.

그래서 마지막 문장은

i = 1 + 1;

i도착합니다 2. 나는 이것이 당신의 두 질문에 모두 대답한다고 생각합니다.

  • i값 2는 어떻게 얻습니까?
  • 경고 메시지가 나타나는 이유는 무엇입니까?

참고 : FWIW, 왼쪽 피연산자 평가 후 시퀀스 포인트(i, ++i, 1)있으므로 일반적으로 실수로 생각할 수 있으므로 UB를 호출하지 않습니다 .


i = (i, ++i, 1) + 1;

단계별로 분석해 봅시다.

(i,   // is evaluated but ignored, there are other expressions after comma
++i,  // i is updated but the resulting value is ignored too
1)    // this value is finally used
+ 1   // 1 is added to the previous value 1

그래서 우리는 2를 얻습니다. 그리고 마지막 과제는 :

i = 2;

지금 덮어 쓰기 전에 i에 있던 것이 무엇이든간에 .


의 결과

(i, ++i, 1)

이다

1

에 대한

(i,++i,1) 

평가는 ,운영자가 평가 된 값을 버리고 가장 정확한 값을 유지하도록 수행됩니다.1

그래서

i = 1 + 1 = 2

쉼표 연산자 에 대한 위키 페이지에서 유용한 정보를 찾을 수 있습니다.

기본적으로

... evaluates its first operand and discards the result, and then evaluates the second operand and returns this value (and type).

This means that

(i, i++, 1)

will, in turn, evaluate i, discard the result, evaluate i++, discard the result, and then evaluate and return 1.


You need to know what the comma operator is doing here:

Your expression:

(i, ++i, 1)

The first expression, i, is evaluated, the second expression, ++i, is evaluated, and the third expression, 1, is returned for the whole expression.

So the result is: i = 1 + 1.

For your bonus question, as you see, the first expression i has no effect at all, so the compiler complains.


Comma has an 'inverse' precedence. This is what you will get from old books and C manuals from IBM (70s/80s). So the last 'command' is what is used in parent expression.

In modern C its use is strange but is very interesting in old C (ANSI):

do { 
    /* bla bla bla, consider conditional flow with several continue's */
} while ( prepAnything(), doSomethingElse(), logic_operation);

While all operations (functions) are called from left to right, only the last expression will be used as a result to conditional 'while'. This prevent handling of 'goto's to keep a unique block of commands to run before condition check.

EDIT: This avoid also a call to a handling function which could take care of all logic at left operands and so return the logical result. Remember that, we had not inline function in the past of C. So, this could avoid a call overhead.

참고URL : https://stackoverflow.com/questions/30614396/what-does-i-i-i-1-1-do

반응형