이 버전의 논리 AND C에서 단락 동작이 표시되지 않는 이유는 무엇입니까?


80

예, 이것은 숙제 질문이지만 주제에 대해 조사하고 상당한 양의 깊이 생각을했지만 이것을 이해할 수 없습니다. 질문은이 코드 조각이 단락 동작을 나타내지 않으며 그 이유를 묻습니다. 그러나 그것은 단락 동작을 보이는 것처럼 보이므로 누군가가 왜 그렇지 않은지 설명 할 수 있습니까?

C에서 :

이 경우에 저에게 보이는 a거짓, 프로그램 평가하려고하지 않습니다 b전혀하지만, 내가 잘못해야합니다. b이 경우 프로그램이 터치하지 않아도되는 이유는 무엇 입니까?


11
대부분의 인위적인 숙제 질문의 전형적인 것처럼 프로그래머가 의도적으로 영리 해 지려고하지 않는 한 프로덕션 시스템에서 이런 종류의 코드를 볼 수 없습니다.
Robert Harvey

49
@RobertHarvey 항상 프로덕션 시스템에서 이와 같은 코드를 볼 수 있습니다! 라는 함수는 AND()아니지만 값으로 인수를받은 다음 함수의 논리에 따라 인수를 평가하거나 평가하지 않는 함수는 어디에나 있습니다. "속임수 질문"임에도 불구하고 이해해야 할 C의 중요한 행동입니다. 이름을 부르는 언어에서이 질문은 매우 다른 대답을 갖습니다.
Ben Jackson

7
@BenJackson : 나는 행동이 아니라 코드에 대해 언급하고있었습니다. 예, 행동을 이해해야합니다. 아니요, 이와 같은 코드를 작성할 필요가 없습니다.
Robert Harvey

3
이것은 VB로 코딩해야하고 IIf를 만나는 경우에 실제로 상당히 관련이 있습니다. 운영자가 아닌 기능이므로 평가가 단락되지 않습니다. 이것은 단락 연산자에 익숙한 개발자가 IIf(x Is Nothing, Default, x.SomeValue).
Dan Bryant

3
@alk 는 교육 시스템 기소 이기 때문 입니다.
Shivan Dragon

답변:


118

이것은 속임수 질문입니다. 메서드에 b대한 입력 인수 sc_and이므로 항상 평가됩니다. 다른 단어에서는 sc_and(a(), b())호출 a()하고 호출 한 다음 b()(순서는 보장되지 않음) sc_and결과 를 호출 a(), b()하여 a?b:0. 절대적으로 단락되는 삼항 연산자 자체와는 관련이 없습니다.

최신 정보

내가 이것을 '속임수 질문'이라고 부르는 이유와 관련하여 : '단락'을 고려할 위치에 대한 잘 정의 된 컨텍스트가 부족하기 때문입니다 (적어도 OP에 의해 재현 됨). 함수 정의 만 주어 졌을 때 많은 사람들 은 질문의 맥락 이 함수 의 본문 에 대해 묻는다고 가정 합니다 . 그들은 종종 그 기능을 그 자체로 표현으로 간주하지 않습니다. 이것이 질문의 '속임수'입니다. 일반적으로 프로그래밍에서, 특히 규칙에 대한 많은 예외가있는 C와 같은 언어에서는 그렇게 할 수 없다는 것을 상기시키기 위해. 예를 들어 질문이 다음과 같이 요청 된 경우 :

다음 코드를 고려하십시오. main 에서 호출 될 때 sc_and exibit 단락 동작을 수행합니다 .

sc_and자신의 도메인 특정 언어 에서 그 자체로 운영자로 생각 하고 호출 sc_and이 일반처럼 단락 동작 을 나타내는 지&& 평가 해야한다는 것이 즉시 분명 해질 것 입니다. 삼항 연산자에 초점을 맞추지 않고 대신 C / C ++의 함수 호출 메커니즘에 초점을 맞춰야한다는 것이 분명하기 때문에 트릭 질문이라고 생각하지 않습니다. sc_and단락 을 수행하는 후속 질문에 멋지게 작성하십시오 #define. 이는 함수 가 아닌 사용을 포함 합니다).

삼항 연산자 자체가 단락 (또는 '조건부 평가'와 같은 다른 것)을 수행하는 것을 호출할지 여부는 단락에 대한 정의에 따라 다르며 이에 대한 다양한 의견을 읽을 수 있습니다. 내 생각에는 그렇지만 실제 질문이나 내가 '트릭'이라고 부르는 이유와는별로 관련이 없습니다.


13
삼항 연산자가 단락합니까? 아니요 . ?에서와 같이 다음에 나오는 표현식 중 하나를 평가 if (condition) {when true} else {when-false}합니다. 그것은 단락이라고 부르지 않습니다.
Jens


17
@Jens : 연산자가 하나 이상의 피연산자에 대한 평가를 건너 뛰는 경우를 "단락"형식이라고 부르지 만, 이것은 실제로 용어를 정의하는 방법의 문제 일뿐입니다.
R .. GitHub STOP HELPING ICE

13
에 대한이의 문법 설탕 @Jens if else아닌를 if. 그럼에도 불구하고 실제로는 그렇지 않습니다. ?:연산자는 인 표현 , if-elseA는 . 삼항 표현식 과 동일한 효과를 생성하는 동일한 명령문 세트를 구성 할 수 있더라도 의미 상 매우 다른 것 입니다. 이것이 단락으로 간주되는 이유입니다. 대부분의 다른 표현식은 항상 모든 피연산자 ( 등)를 평가합니다 . 그렇지 않은 경우 단락 ( )입니다. +,-,*,/&&, ||
aruisdante 2014 년

9
예, 저에게 중요한 차이점은 운영자에 대해 이야기하고 있다는 것입니다. 물론 흐름 제어 문 은 실행되는 코드 경로를 제어합니다 . 연산자의 경우 C 및 C 파생 언어에 익숙하지 않은 사람에게는 연산자가 모든 피연산자를 평가하지 않을 수 있다는 사실이 분명하지 않으므로이 속성에 대해 설명하는 용어를 사용하는 것이 중요합니다. 회로 ".
R .. GitHub STOP HELPING ICE

43

성명서

실행하는, b++피연산자 경우 평가되지 a로 평가 false(단락 동작). 이는 부작용이 발생 b하지 않음을 의미합니다 .

이제 함수를 살펴보십시오.

그리고 이것을 불러

이 경우, 여부 a입니다 true또는 false, b++항상 평가됩니다 1 에 함수 호출 및 부작용 중 b항상 일어날 것이다.

같은 사실입니다


1 함수 인수의 평가 순서가 지정되지 않았습니다.


1
좋아요, 그래서 Stephen Quan의 대답을 공증합니다 : 당신이 "bool x = and_fun (a, b ++);"을 호출 할 때, compilar가 "and_fun"함수를 인라인 할 수있는 것이 가능합니까 (합법적)입니까? a가 true이면 b ++가 증가하지 않습니까?
Shivan Dragon 2014

4
@ShivanDragon 저에게 관찰 가능한 행동을 바꾸는 것 같습니다.
sapi

3
@ShivanDragon : 인라인 할 때 컴파일러는 동작을 변경하지 않습니다. 이 글은 함수 본문을 대체하는만큼 간단하지 않다.
잭 Aidley

명확성을 위해 int x = a ? b++ : 0관찰 가능한 단락으로를 추가 할 수 있습니다 .
Paul Draper 2014 년

@PaulDraper; 독자가 혼동하지 않도록 원본 코드를 그대로 두었습니다.
haccks 2014 년

19

이미 다른 사람들이 지적했듯이, 두 인수로 함수에 전달되는 것이 무엇이든 전달되는대로 평가됩니다. 이것이 테너 리 연산 이전의 방식입니다.

반면에 이것은

이로, "단락" 매크로 함수 호출이와 함수의 인수없이 평가 (들) 수행을 의미하지는 않습니다.


이유를 설명 할 수 있습니까? 작전의 일부와 똑같은 나를 찾습니다. 인라인이 다른 범위에 속하지 않는 것을 제외하고.
dhein 2014 년

5

@cmasters 주석에 명시된 오류를 수정하도록 편집되었습니다.


... returned 표현식은 단락 평가를 나타내지 만 함수 호출은 그렇지 않습니다.

전화 해보세요

함수 호출 1 / 0은 사용되지 않지만 평가 하므로 0으로 나누기 오류가 발생할 수 있습니다.

ANSI C 표준 (초안)에서 발췌 한 관련 내용은 다음과 같습니다.

2.1.2.3 프로그램 실행

...

추상 기계에서 모든 표현식은 의미 체계에 지정된대로 평가됩니다. 실제 구현은 해당 값이 사용되지 않고 필요한 부작용이 발생하지 않는다고 추론 할 수있는 경우 표현식의 일부를 평가할 필요가 없습니다.

3.3.2.2 함수 호출

....

의미론

...

함수 호출을 준비 할 때 인수가 평가되고 각 매개 변수에 해당 인수의 값이 할당됩니다.

내 생각 엔 각 인수는 전체 인수 목록이라고 표현으로 평가되지만 있다는 것입니다 하지 따라서 비 SCE 동작은 필수입니다, 식.

C 표준의 심해 표면에 대한 스 플래셔로서 저는 두 가지 측면에 대한 적절한 정보에 감사드립니다.

  • 평가 1 / 0가 정의되지 않은 동작을 생성 합니까 ?
  • 인수 목록이 표현식입니까? (나는 그렇게 생각하지 않는다)

추신

C ++로 이동 sc_and하고 inline함수 로 정의하더라도 SCE를 얻지 못합니다 . @alk 처럼 C 매크로로 정의 하면 확실히 그렇게 될 것입니다.


1
아니요, inline함수는 함수 호출의 의미를 변경하지 않습니다. 그리고 이러한 의미 올바르게 인용 한대로 모든 인수 평가 되도록 지정합니다 . 컴파일러는 호출을 최적화 할 수 있습니다하더라도, 눈에 보이는 행동은 즉, 변경해서는 안 sc_and(f(), g())모두 것처럼 행동해야 f()하고 g()항상라고합니다. sc_and(0, 1/0)이 때문에 나쁜 예입니다 입니다 정의되지 않은 동작은, 컴파일러가도 호출 할 필요가 없습니다 sc_and()...
cmaster - 분석 재개 모니카

@cmaster 감사합니다. 나는 단순히 C ++가 inline호출 의미를 보존 한다는 것을 몰랐다 . 저는 제로-디바이드를 사용했습니다. 예제에 적합하기 때문에 SCE는 정의되지 않은 동작 을 피하기 위해 종종 악용됩니다 .
미리보기

4

삼항 연산 단락을 명확하게 보려면 정수 대신 함수 포인터를 사용하도록 코드를 약간 변경해보십시오.

그런 다음 컴파일하십시오 (거의 최적화 없이도 : -O0!). 당신은 볼 b()경우 실행되지 않습니다 a()반환 거짓.

생성 된 어셈블리는 다음과 같습니다.

따라서 다른 사람들이 올바르게 지적했듯이 질문 트릭은 단락하지 않는 호출 (값별 호출)에 대한 매개 변수 평가 대신 단락 ( '조건부 평가'라고 함)을 수행하는 삼항 연산자 동작에 초점을 맞추도록하는 것입니다.


0

C 삼항 연산자는 값이 반환 될 수있는 경우 표현식 bc가 제공하는 값을 결정하기 위해 단일 표현식 a (조건) 만 평가하므로 단락 할 수 없습니다 .

다음 코드 :

다음 코드와 거의 동일합니다.

표현식 a 는 && 또는 ||와 같은 다른 연산자로 구성 될 수 있습니다. 값을 반환하기 전에 두 개의 표현식을 평가할 수 있기 때문에 단락 될 수 있지만 단락을 수행하는 삼항 연산자로 간주되지 않고 일반 if 문에서와 같이 조건에서 사용되는 연산자로 간주됩니다.

최신 정보:

삼항 연산자가 단락 연산자라는 논쟁이 있습니다. 인수는 모든 피연산자를 평가하지 않는 모든 연산자가 아래 주석의 @aruisdante에 따라 단락을 수행한다고 말합니다. 이 정의가 주어지면 삼항 연산자가 단락되고 이것이 원래 정의 인 경우 동의합니다. 문제는 "단락 (short-circuit)"이라는 용어가 원래 이러한 동작을 허용하는 특정 종류의 연산자에 사용되었으며 논리 / 부울 연산자이며 그 이유 만 설명하려고한다는 것입니다.

문서 다음 단락 평가 , 단락 평가는 첫 번째 피연산자가 첫 번째 피연산자 인 && 연산자, 이것이 두 번째 무관 할 것으로 알고있는 방식으로 언어로 구현 부울 연산자 칭한다 거짓 , 그리고 || 연산자는 첫 번째 피연산자 true 이며 C11 사양 은 6.5.13 논리 AND 연산자 및 6.5.14 논리 OR 연산자에서도이를 기록합니다.

즉, 단락 동작을 식별하려면 첫 번째 피연산자가 두 번째 피연산자와 관련이없는 경우 부울 연산자처럼 모든 피연산자를 평가해야하는 연산자에서이를 식별해야합니다. 이는 단락이 논리 연산자에서 발생하기 때문에 MathWorks 의 "논리적 단락"섹션에서 단락에 대한 다른 정의에 기록 된 내용과 일치 합니다.

내가 삼항 연산자라고도하는 C 삼항 연산자를 설명하려고했지만 피연산자 중 두 개만 평가하고 첫 번째 피연산자를 평가 한 다음 두 번째 피연산자를 평가합니다. 첫 번째. 항상 이렇게합니다. 어떤 상황에서도이 세 가지를 모두 평가해서는 안되므로 어떤 경우에도 "단락"이 없습니다.

항상 그렇듯이, 무언가가 옳지 않다는 것을 알게된다면, 단지 반대표가 아니라 이에 반대하는 의견을 적어주세요. 이것은 단지 SO 경험을 더 악화시킬뿐입니다. 그리고 저는 우리가 단지 대답 만하는 훨씬 더 나은 커뮤니티가 될 수 있다고 믿습니다. 하나는 동의하지 않습니다.


3
그리고 왜 반대표를 던졌습니까? 내가 잘못 말한 것을 고칠 수 있도록 댓글을 원합니다. 건설적이어야합니다.
Adrián Pérez

2
100 % On Topic이 아니기 때문에 -1 일 수도 있습니다. 그러나 어쨌든 나는 당신의 대답이 적어도 statemant를 설명하고 잘못된 ompv가 아닌 것 같기 때문에 +1을주었습니다.
dhein 2014-10-14

4
@AdrianPerez는 왜 대부분의 사람들이 삼차 연산자를 단락 회로로 간주하는지에 대한 내 대답의 주석 섹션을 참조하십시오. 일부 피연산자의 값을 기반으로 모든 피연산자를 평가하지 않는 표현식입니다. 그것은 단락입니다.
aruisdante 2014 년

3
모든 피연산자를 평가하지 않는 부울이 아닌 연산자를 생각할 수 없습니다. 그러나 그것은 요점 외에 있습니다. 이 단락 불리는 이유는 precisley입니다 때문에 그것이의 연산자 (또는 일반적인 의미에서, 표현보다는 문) 수행의 모든 피연산자를 평가하지. 연산자의 유형은 실제로 중요하지 않습니다. 단락되지 않은 부울 연산자를 작성하는 것이 완벽하게 가능할 것이며 마찬가지로 부울이 아닌 연산자도 작성할 수 있습니다 (예 : 0의 정수 다중화는 항상 0이므로 첫 번째 피연산자가 0이면 즉시 0을 반환).
aruisdante 2014 년

2
x = a ? b : 0;같은 의미 동일합니다(a && (x = b)) || (x = 0);
JXH
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.