“i ++ == ++ i”인 경우 C 개발자가 왜 그렇게 궁금해합니까? [닫은]


15

임의의 관찰 결과, StackOverflow.com에서 "++ i == i ++"에 대한 질문이있는 것 같습니다. 그래도 그 질문은 항상 묻습니다. 지난 2 개월 동안 6 번 또는 7 번 정도 묻는 것을 보았습니다.

C 개발자가 왜 그렇게 관심이 있는지 궁금합니다. C # 및 Java 개발자에게도 동일한 개념 / 질문이 있지만 C # 관련 질문은 하나만 보았습니다.

많은 예제가 ++ i를 사용하기 때문입니까? 인기있는 책이나 튜토리얼이 있기 때문입니까? C 개발자가 '효율성'/ '성능'을 위해 가능한 한 줄에 넣는 것을 좋아하기 때문에 ++ 연산자를 사용하여 '이상한'구조를 자주 만나기 때문입니까?


23
(C # dev로, i ++과 ++ i는 동일합니다. 나는 그것들이 아니라는 것을 알고 있지만, 그 차이에 의존하는 코드를 작성하면 더 읽기 쉽도록 리팩터링하고 컴파일러와 JITter가 돌볼 것을 기대합니다 그것의, 그러나 C # 개발자로서 나는 어쨌든 이미 비효율적이기 때문에 하나 또는 두 개의 클럭 사이클을 절약하려고하지 않습니다)
Michael Stum

1
신진 프로그래머로서 우리는 산술, 논리를 가지고 노는 것을 좋아하고 일이 어떻게 작동하는지 궁금합니다. 우리가 멍청한 놈들이 그런 질문을 좋아하는 큰 이유라고 생각합니다. 그것은 길을 잃는 기능은 아니지만 재미 있습니다! 우리가 프로그래머가 된 이유가 처음이 아닙니다!
Chani

2
말 그대로 표현 ++i == i++을 의미 합니까? 보다 일반적으로 ++i와의 의미 차이에 대해 말하고 i++있습니까?
키이스 톰슨

답변:


30

나는 그것의 적어도 일부가 조금 더 단순하다고 생각합니다. 지금도 우리는 학년도 초반에 이와 같은 많은 질문을보고 점차적으로 점점 줄어 듭니다.

따라서, 나는 그들 중 상당수가 단순히 교사가 그것에 대해 조금 이야기하는 수업의 결과라고 생각하지만 그의 요점을 잘 설명하지는 않습니다. 그는 자신을 실제로 이해하지 못하기 때문에). 특히 이러한 질문을하는 사람들을 기준으로 실제 코딩을 기반으로하는 사람은 거의 없습니다.


14
이것이 영원한 9 월 의 반대 가 아닌가 ? 영원한 9 월 은 AOL이 고객에게 유즈넷 액세스를 제공하기 시작한시기로, 9 월 (학교를 시작하는 새로운 학생들이 전통적으로 초보자로 보드를 공격 한 달)처럼 보입니다.
nlawalker

흥미로운 이론이지만 누군가가 자료를 이해하지 못하면 교사의 잘못이 아닐 수도 있습니다. 아마도 학생들이 (1) 수업 중 충분한주의를 기울이지 않았으며 (2) 전에 스택 오버 플로우에 대한 답변을 찾기에는 너무 게으른 것 같습니다 같은 질문을 다시합니다.
조르지오

12

C 프로그래머는 작업 순서를 이해해야하기 때문입니다. C # 개발자는 일반적으로 다른 것들에 대해 더 걱정하기 때문에 비트 연산자 (&, |, ~) 또는 접두사 연산자를 반드시 사용할 필요는 없습니다. 그러나 C # 개발자가 깨닫지 못하는 것은 매일 사용하는 연산자와 해당 연산자를 올바르게 사용하는 방법을 알아야한다는 것입니다. 우리 대부분은 이것이 문제가 될 수있는 장소를 피합니다.

머리 위로,이 스 니펫의 결과는 무엇입니까?

    double x = 5.5;
    Console.WriteLine(x++);
    x = 5.5;
    Console.WriteLine(++x);

나는 노련한 C # 개발자들이 콘솔에 대한 출력이 무엇인지 전혀 모른다고 말합니다.


3
+1. 사전 및 사후 수정 증분 / 감소 연산자의 차이점을 아는 것은 이와 같은 상황에 적합합니다.
Maulrus

4
나는 요점을 보았고 출력도 알지 못했을 것입니다 (5.5와 6.5라고 생각하지만 확실하지 않습니다). Console.WriteLine (x); 바로. 나는 완전히 무지하지는 않지만 단지 유용성이 전혀없는 큰 코드 냄새라고 생각합니다.
Michael Stum

9
질문에 대한 답변은 작업 순서 또는 접두사와 접미사 증분의 차이와 관련이 없습니다. 정의되고 정의되지 않은 동작의 문제입니다.
David Thornley

2
나는 오늘 이것을 만났다. 같은 것 if (myList[i++] == item). 영리한. IndexOutOfRange 예외의 원인을 찾는 것을 발견했습니다 ... 실제로 "영리한".
rmac

7
나는 그것이 5.5와 6.5라고 생각하지만 ++, 전에 플로트 에서 사용 된 적이 없으며 , 그것이 적절하지 않다고 말해야합니다. 사람들이 그렇게합니까? (바람직 += 1)
Bart van Heukelom

8

나는 이것이 명백하다고 생각한다. C #을에서, 대한 int i, i++ == ++i허위 동안은 항상 ++i == i++안정적으로, 항상 true이며, 관심있는 사람은 (그냥 실행하여 실제로 나)의 C #의 규칙을 학습하여 쉽게를 확인할 수 있습니다.

반면 C와 C ++에서는 컴파일러, 실행 환경, 플랫폼 등에 의존하기 때문에 정의되지 않은 상태에 가깝기 때문에 대답하기가 훨씬 더 어렵 기 때문에 많은 사람들이 묻는다.


+1-대답하기 어려운 질문은 아닙니다. "정의되지 않음"은 한 단어입니다. 모든 "그것은 ~에 의존한다"는 것은 대부분의 사람들이 걱정하지 않는 것들이다. 하나의 특정 플랫폼에 대해서만 작성하더라도 언어 전체에 대한 일반적인 관용구를 사용해야하며 사전 증분 및 사후 증분 연산자의 대부분의 사용은 몇 가지 일반적인 관용구의 일부입니다.
Steve314

+1 : 이것은 실제로 질문에 대답합니다 (즉, 줄 사이를 읽지 않습니다).
Thomas Eding

7

속임수 질문이기 때문에 인기있는 질문입니다. undefined 입니다.

위의 링크는 Bjarnes Stroustrup의 홈페이지에 대한 FAQ로 이동하여이 질문을 구체적으로 다루고이 구성이 정의되지 않은 이유를 설명합니다. 그것이 말하는 것 :

기본적으로 C 및 C ++에서는 변수를 작성하는 표현식에서 변수를 두 번 읽는 경우 결과가 정의되지 않습니다.

평가 순서를 정의하지 않으면 성능이 더 우수한 코드를 생성 할 수 있습니다.


5

아마도 C에서는 글을 i++쓰거나 ++i포인터 산술을 할 때 중요합니다 . i작업 전후 에 증가 하는 것이 중요 할 수 있습니다. 예를 들지만 C를 마지막으로 쓴 것은 10 년 전이었습니다.

C #에서 나는 for / while 루프에 대해 AFAIK 에 대해 생각 i++하거나 생각해야 할 상황을 결코 보지 못했습니다 ++i.


3
C #의 차이점을 이해하는 것이 여전히 중요합니다. for / each 루프에서만 사용한다고해서 이것이 유일한 위치를 의미하지는 않습니다.
STW

완전히 사실입니다.
Mladen Prajdic

3
이것은 질문과 관련이 없습니다. 질문의 차이에 대해하지 않습니다 i++++i하지만 같은 표현에서 그들을 결합.
David Thornley

@David 문제는 C 프로그래머가 궁금한 이유입니다. 그 대답은 (C #에서는 그리 중요하지 않습니다.) 완전히 관련이 있습니다. "
Florian F

2

몇 년 전에 나는이 연산자들이 위험한 것으로 간주되어 더 많은 정보를 찾으려고했습니다. 그 당시 스택 오버 플로우가 발생했다면 거기에 물었을 것입니다.

꼬인 사람들이 다음과 같은 루프를 작성하기 때문입니다.

while( [something] )
{
  a[++j] = ++j;
}

지금도 어떤 일이 일어날 지 잘 모르겠지만 같은 줄에 여러 개의 ++ [var]가 문제를 요구하고 있다는 것이 분명합니다.


2
C에서 할당의 일부로 증분이 정의되지 않은 동작이 있음
tzenes

7
같은 할당 x = ++j;은 C에서 잘 정의되어 있습니다. 위의 내용은 j중간 시퀀스 포인트없이 두 번 수정 되었으므로 정의되지 않았습니다 .
Matthew Flaschen

2

두 가지 이유가 있습니다.

++ i의 올바른 구현은 i를 증가시킨 다음 반환하는 것입니다. i ++의 올바른 구현은 현재 값을 저장하고 i를 증가시킨 후 저장된 값을 리턴하는 것입니다. 이것들이 동의어로서 구현되지 않는다는 것을 아는 것이 중요합니다.

문제 는 컴파일러가 평등과 같은 표현식을 평가하는 동안 언제 그것들을 적용 하는가 가 됩니다 .

평등 테스트를 먼저 수행 한 다음 증분 및 사후 증분 연산자를 수행하는 경우 왼쪽 (lhs) 및 오른쪽 (rhs)을 먼저 평가하는 경우와 다른 논리를 작성해야합니다. 평등.

그것은 모든 작업 순서에 관한 것이며, 차례로 작성하는 코드에 영향을 미칩니다. 그리고 놀랍게도 모든 언어가 동의하는 것은 아닙니다.

기본 테스트 목록을 통해 개발자는 실제 구현이 언어 사양과 일치하는지뿐만 아니라 자신의 가정이 올바른지 테스트 할 수 있습니다.

포인터, 루프 또는 반환 값으로 작업 할 때 모든 종류의 영향을 미칠 수 있습니다.


5
이것에 대한 기본 테스트는 정의되지 않은 동작이기 때문에 오해의 소지가 있습니다. 이번에 예상 한대로 정확하게 작동하면 다음에 보장 할 수 없습니다.
David Thornley

당신은 잘못된 질문에 대답했습니다. C 프로그래머가 왜 궁금한지 대답해야합니다.
휴고

두 번째 매개 변수++i 는 어쨌든 올바르지 않습니다 (적어도 C ++ 11 이전). 동작은 i+1특정 시점, 어쩌면 그 전후에, 다음 시퀀스 포인트 전에 증가를 사용하는 것i 입니다.
MM

@MattMcNabb-사양을 알려 주시면 구현에 변화가 있는지 궁금합니다. C가 PDP 어셈블리에 멋지게 매핑했던 시절에 ++ i는 INC 명령어를 삽입했지만 접미사 버전은 증분 후 명령어를 사용하기 위해 레지스터에 값을 복사해야했습니다. 당신이 묘사 한 변화의 필요성은 무엇입니까?
Walt Stoneburner

2

문화 충격이라고 생각합니다.

이미 지적했듯이 사후 증가 등의 실행 순서가 엄격하게 정의되어 있지 않기 때문에 C 또는 C ++에서 표현식의 동작을 정의 할 수 없습니다. 정의되지 않은 동작은 C에서 매우 일반적이며 C ++로 가져 왔습니다.

다른 언어로 프로그래밍을 한 사람에게-프로그래밍 언어가 정확해야한다고 생각하고 컴퓨터가 지시받은 것을 수행해야한다는 생각을 가진 사람에게는 충격입니다. C가 의도적으로 일부 사항에 대해 모호하다는 것을 발견하십시오.


C는 생각할 수있는 가장 이상한 임베디드 또는 메인 프레임 플랫폼을 포함하여 C #이 정의되었을 때보 다 훨씬 더 많은 플랫폼을 지원하도록 설계 되었기 때문에 이런 방식입니다. 반면에 C #은 ... x86 및 360에서 실행됩니까? 아마 ARM도? 다른 건 없어 이것이 C #이 더 많은 것을 정의 할 수있는 이유입니다.
DeadMG

++ 또한 C는 PDP-11을 기반으로 처음 구축되지 않았습니까? 자동 증분 지시는 어디에 있었습니까? C는 명령어 세트를 유용하게 사용할 수 있도록 "머신에 가깝게"있기를 원했습니다.
Mike Dunlavey

@MikeDunlavey : 아니요. C ++--운영자는 PDP-11을 기반으로하지 않았 으며 , CDP 가 이전 언어 B로 도입되었을 때는 없었습니다. cm.bell-labs.com/who/dmr/chist.html 및 "자동 증가"를 검색하십시오.
키이스 톰슨

1

아마도 C 개발자가 일반적으로 ++ 증분을 더 자주 사용하는 것입니다. C에 배열을 반복하는 "foreach"나 이와 유사한 문이없는 방식으로 생각하십시오. 아, 물론 앞서 언급했듯이 포인터 산술!


1
좋은 점은 foreach가 상대적으로 현대적인 개념이라는 것을 잊었습니다.
Michael Stum

-1

두 부분의 차이점 : 게시물과 사전 증가는이 두 코드 조각이 모든 언어에서 작동하는 방식으로 작동합니다. 이것은 언어에 의존하지 않습니다 !!!

++i

이것은 사전 증분입니다. 이 코드는 i값을 사용하는 행으로 값을 보내기 전에 먼저 값을 증가시킵니다 .

i++

이것은 포스트 증분입니다. 이 코드 는 사용되는 줄 i의 값을 늘리기 전에 값을 반환합니다 i.

또 다른 작은 예에서 :

int main(void)
{
  int i = 0; 
  int result; 
  result = 10 + ++i; 
  printf("%d \n", result); // = 11 

  int j = 0; 
  result = 10 + j++; 
  printf("%d \n", result);// = 10
  return 0;
}

이 코드는 코드 패드에서 결과를 컴파일합니다.

이것은 연산자 오버로딩의 내부 구현과 관련이 있습니다.

++i 직접 값을 증가시킵니다 (따라서 조금 더 빠릅니다)

i++먼저 필요한 곳에 사본을 생성 한 다음 i변수 의 원래 값을 1 씩 증가시킵니다.

나는 이것이 분명해지기를 바랍니다.


그러나 이것이 실제 질문을 다루지는 않습니다. 왜 C 개발자가 다른 것에 비해 더 많은 것을 묻습니까? OP는 운영자를 이해합니다.
Martijn Pieters

또한이 대답은 실제로 틀립니다. ++i더 빠르지 i++않으며 사본을 만들지 않습니다. 또한 ++iC에서 C ++보다 약간 다르게 동작합니다.
MM
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.