C의 3진수(조건부) 연산자
조건부 연산자는 무엇이 필요합니까?if-else 구문을 구현하기 때문에 기능적으로는 장황합니다.조건부 연산자가 동등한 if-else 할당보다 더 효율적이면 왜 if-else를 컴파일러에 의해 더 효율적으로 해석할 수 없는가?
3진 연산자는 구문적이고 읽기 쉬운 편리함이지 성능 단축키가 아닙니다.복잡성이 다양한 조건 때문에 사람들은 그것의 장점에 대해 의견이 분분하지만, 짧은 조건이라면 한 줄의 표현을 하는 것이 유용할 수 있다.
게다가 찰리 마틴이 쓴 것처럼 표현이기 때문에, 그것은 C의 문장의 오른쪽에 나타날 수 있다는 것을 의미합니다.이것은 간결하기 때문에 가치가 있다.
C에서는 문장이 아닌 표현이라는 것이 진정한 효용입니다.즉, 문장의 오른쪽(RHS)에 표시할 수 있습니다.그래서 어떤 것을 좀 더 간결하게 쓸 수 있어요.
다음과 같은 코드 난독화에 매우 중요합니다.
Look-> See?!
No
:(
Oh, well
);
을 사용하다 아무도 이 시행에 이 될 수 하지 않은 .const
결하간
다음과 같은 경우:
const int n = (x != 0) ? 10 : 20;
n
는 조건문에 따라 초기값이 달라지는 것입니다.가장 쉬운 대안은 만드는 것이다.n
푼도const
, 보통, 보통, 보통, 보통, 보통이 될 수 if
초기화합니다.하지만 네가 원한다면const
, 그것은 보통으로는 할 수 없다.if
가장 좋은 방법은 다음과 같은 도우미 기능을 사용하는 것입니다.
int f(int x) {
if(x != 0) { return 10; } else { return 20; }
}
const int n = f(x);
하지만 버전이 훨씬 더 콤팩트하고 거의 틀림없이 더 읽기 쉽다면 삼진법이다.
콤팩트성 및 if-then-else 구문을 식에 인라인화하는 기능.
C에서 보다 불명확한 연산자 중 일부는 결과를 반환하는 단일 표현식으로서 다양한 함수형 매크로의 구현을 허용하기 때문에 존재한다. '아까부터'의 할수 있습니다.
?:
★★★★★★★★★★★★★★★★★」,
연산자의 기능이 장황한 경우에도 연산자의 존재는 허용됩니다.2개의 파라미터 중 가장 큰 파라미터를 반환하는 함수형 매크로를 실장하고 싶다고 합니다.그 후, 다음과 같이 호출됩니다.
int x = LARGEST(1,2);
이것을 기능적인 매크로로서 실장하는 유일한 방법은,
#define LARGEST(x,y) ((x) > (y) ? (x) : (y))
그건 불가능할 거야
if ... else
결과값을 반환하지 않기 때문에 스테이트먼트를 지정합니다.Note)또 다른 목적은
?:
실제로 가독성을 높인다는 것입니다.가장 자주if...else
가독성은 높지만 항상 그렇지는 않습니다.예를 들어 길고 반복적인 switch 문을 예로 들어 보겠습니다.switch(something) { case A: if(x == A) { array[i] = x; } else { array[i] = y; } break; case B: if(x == B) { array[i] = x; } else { array[i] = y; } break; ... }
이것은 훨씬 읽기 쉬운 것으로 대체할 수 있다.
switch(something) { case A: array[i] = (x == A) ? x : y; break; case B: array[i] = (x == B) ? x : y; break; ... }
주의하시기 바랍니다.
?:
보다 빠른 코드를 얻을 수 없습니다.if-else
그것은 혼란스러운 초보자들이 만들어낸 이상한 신화이다.최적화된 코드의 경우,?:
와 같은 퍼포먼스를 발휘합니다.if-else
대부분의 경우에서요.오히려,
?:
보다 느릴 수 있다if-else
이는 사용되지 않는 오퍼랜드에서도 필수 암묵적 유형의 프로모션이 포함되어 있기 때문입니다.그렇지만?:
보다 더 빠를 수 없다if-else
.
Note) 물론 누군가는 왜 기능을 사용하지 않는지 의아해 할 것이다.실제로 함수를 사용할 수 있는 경우에는 항상 함수와 같은 매크로보다 선호됩니다.하지만 기능을 사용할 수 없는 경우도 있습니다.예를 들어 다음과 같이 가정합니다.x
위의 예에서는 파일 범위로 선언되어 있습니다.이니셜라이저는 상수 표현이어야 하므로 함수 호출을 포함할 수 없습니다.기능과 같은 매크로를 사용해야 하는 다른 실용적인 예로는 Type Safe 프로그래밍을 사용합니다._Generic
또는 "X 매크로"를 선택합니다.
C에는 기술적으로 필요하지 않은 것들이 많이 있습니다. 왜냐하면 그것들은 다른 면에서 어느 정도 쉽게 구현될 수 있기 때문입니다.다음은 불완전한 목록입니다.
- 하는 동안에
- 위해서
- 기능들
- 구조
이것들이 없다면 당신의 코드가 어떻게 생겼을지 상상해 보세요.그러면 답을 찾을 수 있을 겁니다.삼원 연산자는 "통사설탕"의 한 형태로, 주의와 기술로 사용하면 코드를 더 쉽게 쓰고 이해할 수 있습니다.
아직 아무도 말을 안 했으니 똑똑해지는 유일한 방법은printf
스테이트먼트는 3진 연산자를 사용합니다.
printf("%d item%s", count, count > 1 ? "s\n" : "\n");
주의: C에서 C++로 이행하면 오퍼레이터의 우선순위에 몇 가지 차이가 있으며, 이로 인해 발생하는 미묘한 오류에 놀랄 수 있습니다.
dwn이 말한 것처럼 퍼포먼스는 복잡한 프로세서의 출현에 따른 이점 중 하나였습니다.MSDN 블로그 Non-classical processor behavior: 어떤 일을 하는 것이 하지 않는 것보다 더 빠를 수 있다는 것은 3진 연산자와 if/else 문장의 차이를 명확하게 나타내는 예를 제시합니다.
다음 코드를 지정합니다.
#include <windows.h>
#include <stdlib.h>
#include <stdlib.h>
#include <stdio.h>
int array[10000];
int countthem(int boundary)
{
int count = 0;
for (int i = 0; i < 10000; i++) {
if (array[i] < boundary) count++;
}
return count;
}
int __cdecl wmain(int, wchar_t **)
{
for (int i = 0; i < 10000; i++) array[i] = rand() % 10;
for (int boundary = 0; boundary <= 10; boundary++) {
LARGE_INTEGER liStart, liEnd;
QueryPerformanceCounter(&liStart);
int count = 0;
for (int iterations = 0; iterations < 100; iterations++) {
count += countthem(boundary);
}
QueryPerformanceCounter(&liEnd);
printf("count=%7d, time = %I64d\n",
count, liEnd.QuadPart - liStart.QuadPart);
}
return 0;
}
서로 다른 경계에 대한 비용은 훨씬 다르고 희박하다(원재료 참조).한편 변경 시:
if (array[i] < boundary) count++;
로.
count += (array[i] < boundary) ? 1 : 0;
다음과 같은 이유로 실행 시간은 경계값과 독립적입니다.
최적기는 3진 표현에서 분기를 제거할 수 있었습니다.
그러나 데스크톱 인텔 i5 cpu/windows 10/vs2015에서는 msdn 블로그와 테스트 결과가 많이 다릅니다.
디버깅 모드를 사용하는 경우 if/displict 비용:
count= 0, time = 6434
count= 100000, time = 7652
count= 200800, time = 10124
count= 300200, time = 12820
count= 403100, time = 15566
count= 497400, time = 16911
count= 602900, time = 15999
count= 700700, time = 12997
count= 797500, time = 11465
count= 902500, time = 7619
count=1000000, time = 6429
및 삼원 연산자 비용:
count= 0, time = 7045
count= 100000, time = 10194
count= 200800, time = 12080
count= 300200, time = 15007
count= 403100, time = 18519
count= 497400, time = 20957
count= 602900, time = 17851
count= 700700, time = 14593
count= 797500, time = 12390
count= 902500, time = 9283
count=1000000, time = 7020
릴리스 모드를 사용하는 경우 if/interval 비용:
count= 0, time = 7
count= 100000, time = 9
count= 200800, time = 9
count= 300200, time = 9
count= 403100, time = 9
count= 497400, time = 8
count= 602900, time = 7
count= 700700, time = 7
count= 797500, time = 10
count= 902500, time = 7
count=1000000, time = 7
및 삼원 연산자 비용:
count= 0, time = 16
count= 100000, time = 17
count= 200800, time = 18
count= 300200, time = 16
count= 403100, time = 22
count= 497400, time = 16
count= 602900, time = 16
count= 700700, time = 15
count= 797500, time = 15
count= 902500, time = 16
count=1000000, time = 16
3진수 연산자가 내 기계에서 if/internal 스테이트먼트보다 느립니다!
따라서 다른 컴파일러 최적화 기법에 따라 3차 연산자와 if/internal 동작은 크게 다를 수 있습니다.
때로는 3진 연산자가 작업을 완료하는 가장 좋은 방법이기도 합니다.특히 3진수의 결과가 l-값이 되기를 원하는 경우.
이것은 좋은 예는 아니지만, 나는 더 나은 것에 대해 아무것도 말하고 있지 않다.하나는 certian입니다만, 저는 아직 많이 사용하고 있습니다만, 굳이 삼진수를 사용할 필요가 있는 경우는 별로 없습니다.
const char* appTitle = amDebugging ? "DEBUG App 1.0" : "App v 1.0";
하지만 내가 경고하고 싶은 한가지는 삼진법을 함께 묶는 것이다.가 된다.
'이것'은 다음과 같습니다.
int myVal = aIsTrue ? aVal : bIsTrue ? bVal : cIsTrue ? cVal : dVal;
편집: 여기 더 나은 예가 있습니다.3진 연산자를 사용하여 참조와 Const 값을 할당할 수 있습니다.이 값을 할당하지 않으면 처리를 위한 함수를 작성할 필요가 있습니다.
int getMyValue()
{
if( myCondition )
return 42;
else
return 314;
}
const int myValue = getMyValue();
다음과 같은 경우가 있습니다.
const int myValue = myCondition ? 42 : 314;
어느 것이 더 나은가 하는 것은 논쟁의 여지가 있는 질문이다.
3진수 = if-simple 형식의 단순한 if-simple.대부분 읽기 쉽게 사용할 수 있습니다.
와 같다
if(0)
do();
if(0)
{
do();
}
3차 연산자는 문이 아닌 표현식이기 때문에 표현식의 일부로 사용되는 함수형 매크로의 매크로 확장에 사용할 수 있습니다.Const는 원래 C의 일부가 아닐 수도 있지만 매크로 프리프로세서는 오래된 것입니다.
어레이 패키지에 매크로를 사용한 어레이 패키지가 있습니다.이 패키지는 바운드 체크된 어레이 액세스에 사용되고 있습니다.체크된 참조의 구문은 다음과 같습니다.aref(arrayname, type, index)
여기서 arrayname은 데이터의 배열 경계와 부호 없는 문자 배열을 포함하는 구조에 대한 포인터이며 type은 데이터의 실제 유형이고 index는 인덱스입니다.이 확장에는 상당한 어려움이 있었습니다(기억으로는 할 수 없습니다). 하지만 바운드 체크에 삼원 연산자를 사용했습니다.
반환된 객체의 다형성이 필요하기 때문에 C에서는 함수 호출로 이 작업을 수행할 수 없습니다.그래서 식에서 타이프 캐스팅을 하기 위해서는 매크로가 필요했습니다.C++에서는 이것을 템플릿 오버로드 함수 호출(아마 오퍼레이터[]의 경우)로 실행할 수 있지만, C에는 그러한 기능이 없습니다.
편집: 버클리 CAD 어레이 패키지(glu 1.4 에디션)의 예를 다음에 나타냅니다.array_fetch 사용 방법에 대한 문서는 다음과 같습니다.
type
array_fetch(type, array, position)
typeof type;
array_t *array;
int position;
배열에서 요소를 가져옵니다.어레이의 경계를 벗어나 참조하려고 하면 런타임 오류가 발생합니다.지정된 위치의 값이 실제로 배열을 참조할 때 사용되는 유형인지 확인하는 기능은 없습니다.
array_definition은 다음과 같습니다(3진 연산자와 콤마 시퀀싱 연산자를 사용하여 올바른 순서로 모든 서브 식을 단일 표현의 일부로 실행합니다).
#define array_fetch(type, a, i) \
(array_global_index = (i), \
(array_global_index >= (a)->num) ? array_abort((a),1) : 0,\
*((type *) ((a)->space + array_global_index * (a)->obj_size)))
array_insert(필요에 따라 C++ 벡터처럼 어레이를 확장)의 확장에는 여러 개의 중첩된 3진 연산자가 포함되어 더욱 복잡합니다.
이것은 구문설탕이며 하나의 문장이 포함된 간단한 if/else 블록을 위한 편리한 줄임말입니다.기능적으로는 양쪽 구조가 동일하게 동작해야 합니다.
언급URL : https://stackoverflow.com/questions/758849/the-ternary-conditional-operator-in-c
'programing' 카테고리의 다른 글
루프 또는 조건 없이 1~1000 인쇄 (0) | 2022.08.23 |
---|---|
Javadoc 태그가 완전하지 않은 경우 Maven은 Java 8에서 작동하지 않습니다. (0) | 2022.08.23 |
Java: 하나의 파일에 여러 클래스 선언 (0) | 2022.08.23 |
scanf()를 사용하여 문자열 크기를 초과하면 안 됩니다. (0) | 2022.08.23 |
서버에서 Vuex + Vue 풀 상태를 1회만 실행 (0) | 2022.08.23 |