조건문에서 쉼표의 장점은 무엇입니까?
다음 if
과 같이 성명서를 작성할 수 있습니다.
if (a == 5, b == 6, ... , thisMustBeTrue)
if
몸 에 들어가기 위해서는 마지막 조건 만 만족해야합니다 .
왜 허용됩니까?
당신의 예를 약간 바꾸어, 이것이
if ( a = f(5), b = f(6), ... , thisMustBeTrue(a, b) )
( =
대신에 유의하십시오 ==
). 이 경우 쉼표는 평가의 왼쪽에서 오른쪽 순서를 보장합니다. constrast에서이
if ( thisMustBeTrue(f(5), f(6)) )
당신은 f(5)
이전 또는 이후에 호출 되었는지 알 수 없습니다 f(6)
.
보다 공식적으로 쉼표를 사용하면 일련의 명령문을 작성하는 데 사용할 수있는 것과 동일한 방식으로 일련 의 표현식 을 작성할 (a,b,c)
수 있습니다 . 그리고 a 가 시퀀스 포인트 (전체 표현식의 끝)를 만드는 것처럼 쉼표도 마찬가지입니다. 시퀀스 포인트 만 평가 순서를 제어합니다 . 이 게시물을 참조하십시오 .;
a; b; c;
;
하지만 물론이 경우에는 실제로 이렇게 작성합니다.
a = f(5);
b = f(6);
if ( thisMustBeTrue(a, b) )
그렇다면 쉼표로 구분 된 일련의 표현식이 ;
구분 된 일련의 명령문보다 선호되는시기는 언제 입니까? 나는 거의 말하지 않을 것입니다. 우변 대체가 단일 표현식이되기를 원하는 경우 매크로에있을 수 있습니다.
요컨대 : 그렇게하는 것이 합법적이지만 if
또는 while
문의 조건 부분에서 쉼표 연산자를 사용하는 것은 일반적으로 의미가 없습니다 (편집 : user5534870이 답변에서 설명하는 것처럼 후자가 때때로 도움이 될 수 있음).
더 정교한 설명 : 구문 함수 (예 : 이니셜 라이저 목록, 변수 선언 또는 함수 호출 / 선언에서 요소 분리) 외에도 C 및 C ++에서는 예 와 같이 ,
일반 연산자+
가 될 수 있으므로 모든 곳에서 사용할 수 있습니다. , 여기서 표현식이 허용됩니다 (C ++에서는 오버로드 할 수도 있음).
대부분의 다른 연산자와의 차이점은 양쪽이 모두 평가되지만 왼쪽 및 오른쪽 표현식의 출력을 어떤 식 으로든 결합하지 않고 오른쪽 표현식 만 반환한다는 것입니다.
누군가 (아마도 Dennis Ritchie)가 어떤 이유로 C가 일반적으로 단일 표현식 만 쓸 수있는 위치에 두 개 이상의 관련없는 표현식을 작성하는 데 구문이 필요하다고 결정했기 때문에 도입되었습니다.
이제 if
성명서 의 조건 은 ( ,
무엇보다도 ) 그러한 장소이며 결과적으로 연산자 를 사용할 수도 있습니다. 그렇게하는 것이 타당하든 말든 완전히 다른 질문입니다! 특히-그리고 예를 들어 함수 호출이나 변수 선언과는 다른-쉼표는 특별한 의미가 없으므로 항상 수행합니다. 왼쪽과 오른쪽의 표현식을 평가하지만 오른쪽의 결과 만 반환합니다. 그런 다음 if
문에서 사용됩니다 .
( non-overloaded ) ,
연산자를 사용하는 것이 합리적 이라고 생각할 수있는 유일한 두 가지 요점 은 다음과 같습니다.
for
루프 의 헤드에서 여러 반복기를 증가 시키려면 :for ( ... ; ... ; ++i1, ++i2){ *i2=*i1; }
C ++ 11 constexpr 함수에서 둘 이상의 표현식을 평가하려는 경우.
이것을 한 번 더 반복하려면 : if
또는 while
문 에서 쉼표 연산자를 사용하는 것은-예에서 보여준 방식으로-현명한 일이 아닙니다. 이것은 C와 C ++의 언어 구문이 코드를 작성할 수있게 해주는 또 다른 예일 뿐이며, 언뜻보기에 예상했던 방식으로 작동하지 않습니다. 더 많이 있습니다 ....
를 들어 if
문장, 외부가 아닌 쉼표 표현에 뭔가 퍼팅의 실제 포인트가 없습니다.
A에 대한 while
문 조건 쉼표 식으로 바꾸어 상기 제 1 부분을 실행 중 루프에 들어갈 때, 또는 반복하는 경우. 코드 복제 없이는 쉽게 복제 할 수 없습니다.
그렇다면 as do
... while
문은 어떻습니까? 루프 자체에 대해서만 걱정하면됩니다. 여기에서도 첫 번째 부분을 루프로 이동하여 쉼표 표현식을 안전하게 바꿀 수는 없습니다.
우선 루프 본문의 변수에 대한 소멸자가 아직 실행되지 않았으므로 차이가있을 수 있습니다. 또 다른 경우, continue
루프 내부의 모든 명령문 은 루프 본문이 아니라 실제로 조건에있을 때만 쉼표 표현식의 첫 번째 부분에 도달합니다 .
이점 은 없습니다 . 쉼표 연산자는 표현식 목록에있는 마지막 표현식 유형이있는 표현식이고 if 문은 부울 표현식을 평가합니다.
if(<expr>) { ... }
with type of <expr> boolean
이상한 연산자는 사실이지만, 함수 호출에서 표현식 목록과 인수 목록을 혼동한다는 점을 제외하면 마술은 없습니다.
foo(<args>)
with <args> := [<expr>[, <expr>]*]
인수 목록에서 쉼표는 인수를 분리하는 데 더 강력하게 바인딩됩니다.
다음은 당신이 얼마나 사악한 지에 따라 약간의 스트레칭입니다.
함수가 참조 또는 포인터를 통해 전달 된 매개 변수를 수정하여 값을 반환하는 상황을 고려하십시오 (잘못 설계된 라이브러리에서 온 것일 수도 있고, 반환 후 할당되지 않음으로써이 값이 무시되지 않도록 보장하기 위해).
void calculateValue(FooType &result) {/*...*/}
그렇다면에 의존하는 조건문을 어떻게 사용 result
합니까?
수정할 변수를 선언 한 다음 if를 사용하여 확인할 수 있습니다.
FooType result;
calculateValue(result);
if (result.isBared()) {
//...
}
이것은 단축 될 수 있습니다
FooType result;
if (calculateValue(result) , result.isBared()) {
//...
}
Which is not really worth while. However, for while
loops there could be some small advantages. If calculateValue
should/can be called until the result is no longer bar
'd, we'd have something like:
FooType result;
calculateValue(result); //[1] Duplicated code, see [2]
while (result.isBared()) {
//... possibly many lines
//separating the two places where result is modified and tested
//How do you prevent someone coming after you and adds a `continue`
//here which prevents result to be updated in the and of the loop?
calculateValue(result); //[2] Duplicated code, see [1]
}
and could be condensed to:
FooType result;
while (calculateValue(result) , result.isBared()) {
//all your (possibly numerous) code lines go here
}
This way the code to update result
is in only one place, and is near the line where its conditions are checked.
maybe unrelated: Another reason why variables could be updated via parameter passing is that the function needs to return the error code in addition to modify/return the calculated value. In this case:
ErrorType fallibleCalculation(FooType &result) {/*...*/}
then
FooType result;
ErrorType error;
while (error = fallibleCalculation(result) , (Success==error && result.isBared())) {
//...
}
but as noted in the comments, you can do this without the comma too:
FooType result;
ErrorType error;
while (Success == fallibleCalculation(result) && result.isBared()) {
//...
}
None whatsoever. The comparisons on a
in that code are completely redundant.
My question is what is the advantage of commas in if
or while
statement? Why is it allowed ?
It exists because statements and expressions are different things in C. A compound expression is a construct that is understood from theory (and some other languages) and would be missing without having added it in the form of the comma. Its use in the for
statement was the original justification of why they needed it.
But, by making the language more complete from a sound theoretical point of view, it later finds uses that nobody planned. The early C++ was a translator that generated C as its output, and having a sequential expression was absolutely essential in allowing inline functions to really generate "in line" logic in the C code.
That includes any place the expression appears, including the condition of an if
statement.
Similarly, it has been used in "interesting" macros. And as much as C++ did away with macros by providing inline functions, as late as up-to-x11 compilers found the Boost FOREACH range loop (eventually, an emulation of the feature added to the language in x11) very handy, and that was a devilishly clever set of macros that involved the comma operator.
(Hmm, the current version expands into multiple statements using chained if
/else
, rather than cramming it all into a single while
.)
Now, there is another way to put any statement into an expression (lambdas), so future crazy business of macros that emulate even newer language features or domain-specific embedded languages might not need to use that anymore.
So, don't write code like that. Unless it's clear and indeed simpler than writing helper functions or splitting into multiple statements.
But it may be just the thing for a macro that you want to easily use in one place and that place is inside the parens of an if
or while
. That could be justified in a domain-specific language hosted inside the C++ source code, or a language emulation feature like (perhaps) an alternative to exception handling used in an embedded real-time system.
In short, it doesn't have a normal good usage. But it's there for completeness and you never know when someone will find it useful.
'development' 카테고리의 다른 글
SSH 세션에서 tmux를 자동으로 시작하는 방법은 무엇입니까? (0) | 2020.12.03 |
---|---|
`float`를 초기화 할 때`float`로 캐스팅하는 것과 접미사로`f`를 추가하는 것의 차이점은 무엇입니까? (0) | 2020.12.03 |
참조로 파이썬 함수 호출 (0) | 2020.12.02 |
React에서 여러 줄 텍스트 문자열을 렌더링하는 방법 (0) | 2020.12.02 |
phpMyAdmin-오류> 잘못된 형식 매개 변수? (0) | 2020.12.02 |