C와 C++에서의 연산자
이것은 C와 C++ 프로그래밍 언어의 연산자의 목록이다. 모든 연산자는 C++에서 존재가 나열된다; 네 번째 열 "C에 포함"은, 연산자가 C에서 또한 나타내는지를 지시한다. 참고로 C는 연산자 오버로딩을 지원하지 않는다.
오버로드되지 않을 때, 연산자 &&, ||, 그리고 , (쉼표 연산자)에 대해, 이곳은 첫번째 피연산자의 평가 후의 순서 포인트이다.
C++는 또한 간결함을 위한 표에 나열되지 않은 형 변환 연산자 const_cast, static_cast, dynamic_cast, 그리고 reinterpret_cast를 포함한다. 이들 연산자의 서식은 우선순위 단계가 중요하지 않다는 것을 의미한다.
C와 C++에서 사용 가능한 연산자의 대부분은 같은 우선순위, 결합법칙, 그리고 의미론과 함께 C#, 자바, 펄, 그리고 PHP와 같은 다른 언어에서 또한 사용 가능하다.
목차 |
표 [편집]
이 표의 목적을 위해, a, b, 그리고 c는 유효한 값 (리터럴, 변수로부터의 값, 또는 반환 값), 개체 이름, 또는 적절하게, lvalue를 나타낸다.
오버로드가능한은 연산자가 C++에서 오버로드가능한 것을 의미한다. "C에서 포함됨"은 C에서 연산자가 있고 의미론적 의미를 가지는 것을 의미한다 (연산자는 C에서 오버로드가능하지 않다).
산술 연산자 [편집]
| 연산자 이름 | 구문 | 오버로드가능한 | C에서 포함됨 | 프로토타입 예제 (T는 모든 자료형이다) | ||
|---|---|---|---|---|---|---|
| T의 멤버로서 | 외부 클래스 정의들 | |||||
| 기본 할당 | a = b |
예 | 예 | T& T::operator =(const T& b); | N/A | |
| 덧셈 | a + b |
예 | 예 | T T::operator +(const T& b) const; | T operator +(const T& a, const T& b); | |
| 뺄셈 | a - b |
예 | 예 | T T::operator -(const T& b) const; | T operator -(const T& a, const T& b); | |
| 단항 덧셈 (정수 승급) | +a |
예 | 예 | T T::operator +() const; | T operator +(const T& a); | |
| 단항 뺄셈 (반수) | -a |
예 | 예 | T T::operator -() const; | T operator -(const T& a); | |
| 곱셈 | a * b |
예 | 예 | T T::operator *(const T& b) const; | T operator *(const T &a, const T& b); | |
| 나눗셈 | a / b |
예 | 예 | T T::operator /(const T& b) const; | T operator /(const T& a, const T& b); | |
| 모듈러 (나머지) | a % b |
예 | 예 | T T::operator %(const T& b) const; | T operator %(const T& a, const T& b); | |
| 증가 | 접두사 | ++a |
예 | 예 | T& T::operator ++(); | T& operator ++(T& a); |
| 접미사 | a++ |
예 | 예 | T T::operator ++(int); | T operator ++(T& a, int); | |
| 참고: C++는 접두사 및 접미사 사이의 증가 연산자를 구별하는 이름없는 더미-매개변수 int를 사용한다. | ||||||
| 감소 | 접두사 | --a |
예 | 예 | T& T::operator --(); | T& operator --(T& a); |
| 접미사 | a-- |
예 | 예 | T T::operator --(int); | T operator --(T& a, int); | |
| 참고: C++는 접두사 및 접미사 사이의 감소 연산자를 구별하는 이름없는 더미-매개변수 int를 사용한다. | ||||||
비교 연산자/관계 연산자 [편집]
| 연산자 이름 | 구문 | 오버로드가능한 | C에서 포함됨 | 프로토타입 예제 (T는 모든 자료형이다) | ||
|---|---|---|---|---|---|---|
| T의 멤버로서 | 외부 클래스 정의들 | |||||
| 같음 | a == b |
예 | 예 | bool T::operator ==(const T& b) const; | bool operator ==(const T& a, const T& b); | |
| 같지 않음 | a != b |
예 | 예 | bool T::operator !=(const T& b) const; | bool operator !=(const T& a, const T& b); | |
| 보다 큼 | a > b |
예 | 예 | bool T::operator >(const T& b) const; | bool operator >(const T& a, const T& b); | |
| 보다 작음 | a < b |
예 | 예 | bool T::operator <(const T& b) const; | bool operator <(const T& a, const T& b); | |
| 보다 크거나 같음 | a >= b |
예 | 예 | bool T::operator >=(const T& b) const; | bool operator >=(const T& a, const T& b); | |
| 보다 작거나 같음 | a <= b |
예 | 예 | bool T::operator <=(const T& b) const; | bool operator <=(const T& a, const T& b); | |
논리 연산자 [편집]
| 연산자 이름 | 구문 | 오버로드가능한 | C에서 포함됨 | 프로토타입 예제 (T는 모든 자료형이다) | ||
|---|---|---|---|---|---|---|
| T의 멤버로서 | 외부 클래스 정의들 | |||||
| 논리적 부정 (NOT) | !a |
예 | 예 | bool T::operator !() const; | bool operator !(const T& a); | |
| 논리적 AND | a && b |
예 | 예 | bool T::operator &&(const T& b) const; | bool operator &&(const T& a, const T& b); | |
| 논리적 OR | a || b |
예 | 예 | bool T::operator ||(const T& b) const; | bool operator ||(const T& a, const T& b); | |
비트 연산자 [편집]
| 연산자 이름 | 구문 | 오버로드가능한 | C에서 포함됨 | 프로토타입 예제 (T는 모든 자료형이다) | ||
|---|---|---|---|---|---|---|
| T의 멤버로서 | 외부 클래스 정의들 | |||||
| 비트 NOT | ~a |
예 | 예 | T T::operator ~() const; | T operator ~(const T& a); | |
| 비트 AND | a & b |
예 | 예 | T T::operator &(const T& b) const; | T operator &(const T& a, const T& b); | |
| 비트 OR | a | b |
예 | 예 | T T::operator |(const T& b) const; | T operator |(const T& a, const T& b); | |
| 비트 XOR | a ^ b |
예 | 예 | T T::operator ^(const T& b) const; | T operator ^(const T& a, const T& b); | |
| 비트 왼쪽 시프트[참고 1] | a << b |
예 | 예 | T T::operator <<(const T& b) const; | T operator <<(const T& a, const T& b); | |
| 비트 오른쪽 시프트[참고 1] | a >> b |
예 | 예 | T T::operator >>(const T& b) const; | T operator >>(const T& a, const T& b); | |
복합 할당 연산자 [편집]
| 연산자 이름 | 구문 | 오버로드가능한 | C에서 포함됨 | 프로토타입 예제 (T는 모든 자료형이다) | ||
|---|---|---|---|---|---|---|
| T의 멤버로서 | 외부 클래스 정의들 | |||||
| 덧셈 할당 | a += b |
예 | 예 | T& T::operator +=(const T& b); | T& operator +=(T& a, const T& b); | |
| 뺄셈 할당 | a -= b |
예 | 예 | T& T::operator -=(const T& b); | T& operator -=(T& a, const T& b); | |
| 곱셈 할당 | a *= b |
예 | 예 | T& T::operator *=(const T& b); | T& operator *=(T& a, const T& b); | |
| 나눗셈 할당 | a /= b |
예 | 예 | T& T::operator /=(const T& b); | T& operator /=(T& a, const T& b); | |
| 모듈러 할당 | a %= b |
예 | 예 | T& T::operator %=(const T& b); | T& operator %=(T& a, const T& b); | |
| 비트 AND 할당 | a &= b |
예 | 예 | T& T::operator &=(const T& b); | T& operator &=(T& a, const T& b); | |
| 비트 OR 할당 | a |= b |
예 | 예 | T& T::operator |=(const T& b); | T& operator |=(T& a, const T& b); | |
| 비트 XOR 할당 | a ^= b |
예 | 예 | T& T::operator ^=(const T& b); | T& operator ^=(T& a, const T& b); | |
| 비트 왼쪽 시프트 할당 | a <<= b |
예 | 예 | T& T::operator <<=(const T& b); | T& operator <<=(T& a, const T& b); | |
| 비트 오른쪽 시프트 할당 | a >>= b |
예 | 예 | T& T::operator >>=(const T& b); | T& operator >>=(T& a, const T& b); | |
멤버와 포인터 연산자 [편집]
| 연산자 이름 | 구문 | 오버로드가능한 | C에서 포함됨 | 프로토타입 예제 (T, T2 및 R은 모든 자료형이다) | ||
|---|---|---|---|---|---|---|
| T의 멤버로서 | 외부 클래스 정의들 | |||||
| 배열 첨자 | a[b] |
예 | 예 | R& T::operator [](const T2& b); |
N/A | |
| 우회 ("a에 의해 포인트된 개체") | *a |
예 | 예 | R& T::operator *(); | R& operator *(T& a); | |
| 참조 ("a의 주소") | &a |
예 | 예 | T* T::operator &(); | T* operator &(T& a); | |
| a에 의해 포인트된 개체의 멤버 b | a->b |
예 | 예 | R* T::operator ->(); |
N/A | |
| 개체 a의 멤버 b | a.b |
아니오 | 예 | N/A | ||
| a에 의해 포인트된 개체의 b에 의해 포인트된 멤버[참고 2] | a->*b |
예 | 아니오 | R T::operator->*(R);[참고 3] | R operator->*(T, R);[참고 3] | |
| 개체 a의 b에 의해 포인트된 멤버 | a.*b |
아니오 | 아니오 | N/A | ||
다른 연산자 [편집]
| 연산자 이름 | 구문 | 오버로드가능한 | C에서 포함됨 | 프로토타입 예제 (T, R, Arg1 및 Arg2는 모든 자료형이다) | ||
|---|---|---|---|---|---|---|
| T의 멤버로서 | 외부 클래스 정의들 | |||||
| 함수 호출 함수 개체를 살펴본다. |
a(a1, a2) |
예 | 예 | R T::operator ()(Arg1 a1, Arg2 a2, …); | N/A | |
| 쉼표 | a, b |
예 | 예 | R& T::operator ,(R& b) const; | R& operator ,(const T& a, R& b); | |
| 삼항 연산자 | a ? b : c |
아니오 | 예 | N/A | ||
| 범위 확인 | a::b |
아니오 | 아니오 | N/A | ||
| Size-of | sizeof(a)[참고 4]sizeof(자료형) |
아니오 | 예 | N/A | ||
| 자료형 식별 | typeid(a)typeid(자료형) |
아니오 | 아니오 | N/A | ||
| 캐스트 | (자료형) a |
예 | 예 | T::operator R() const; | N/A | |
| 참고: 사용자 정의 변환에 대해, 반환 자료형은 절대적 및 필연적으로 연산자 이름과 일치한다. | ||||||
| 저장소 할당 | new 자료형 |
예 | 아니오 | void* T::operator new(size_t x); | void* operator new(size_t x); | |
| 저장소 할당 (배열) | new 자료형[n] |
예 | 아니오 | void* T::operator new[](size_t x); | void* operator new[](size_t x); | |
| 저장소 할당취소 | delete a |
예 | 아니오 | void T::operator delete(void* x); | void operator delete(void* x); | |
| 저장소 할당취소 (배열) | delete[] a |
예 | 아니오 | void T::operator delete[](void* x); | void operator delete[](void* x); | |
참고:
- ↑ 가 나 iostream의 문맥에서, 저자는 각각, “put-to” 또는 "스트림 삽입" 및 “get-from” 또는 "스트림 추출" 연산자로서 << 및 >>를 자주 참조할 것이다.
- ↑ 예제는 스캇 마이어스의 "스마트 포인터를 위한 ->* 연산자 구현하기"에서 찾을 수 있다.
- ↑ 가 나 ->* 연산자가 있는 곳의 경우에는 기본적 구현처럼 작동하고, R 매개변수는 클래스 T의 메서드에서 메서드 포인터가 될 것이고 반환 값은 메서드 매개변수와 함께(오직) 호출될 것을 준비하는 함수 개체의 몇몇 종류가 될 것이다.
- ↑ 괄호들은 자료형의 크기를 받을 때에만, 값의 크기를 받을 때는 필요하지 않다. 그러나, 그들은 보통 관계없이 사용된다.
연산자 우선순위 [편집]
다음은 C와 C++ 언어에서 모든 연산자의 우선순위와 결합법칙을 나열하는 표이다 (연산자는 또한 자바, 펄, PHP 및 많은 다른 최근 언어가 존재할 때, 우선순위는 그 주어진 것과 동일하다[출처 필요]). 연산자는 내림차순 우선순위에서, 위에서 아래로 나열된다. 우선순위 내림차순은 평가의 우선순서를 나타낸다. 표현식을 고려해서, 어떤 행 위에 나열된 연산자는 그것의 더 아래쪽 행 위에 나열된 모든 연산자로 이전에 평가된다. 같은 셀에 있는 연산자 (여기는 셀에 나열된 연산자의 여러 행이 될 수 있다)는 주어진 방향에서, 같은 우선순위와 함께 평가된다. 연산자의 우선순위는 오버로딩에 의해 영향받지않는다.
C와 C++에서 표현식의 구문은 문맥 자유 문법에 의해 지정된다.[출처 필요] 여기에 주어진 표는 문법으로부터 추론되었다.[출처 필요] ISO C 1999년 표준에 대해, 항목 6.5.6 주 71은 C 연산자의 우선순위를 정의하는 사양에 의해 제공되는 C 문법을 정하고, 또한 사양의 항목 순서를 밀접하게 따라가는 문법으로 인한 연산자 우선순위를 정한다:
"[C] 구문 [즉, 문법]은 첫번째 가장높은 우선순위, 하위조항의 주요 하위조항의 순서와 동일한, 표현식의 평가에서 연산자 우선순위를 지정한다."
우선순위 표는, 대부분 적절하지만, 몇 가지 세부 정보를 해결할 수 없다. 특히, 삼원 연산자는 그것의 중간 피연산자로서 어떤 임의의 표현식을 허용함에도 불구하고, 할당 및 쉼표 연산자보다 높은 우선순위가 있는 것으로서 나열된다는 것을 참고한다. 그러므로 a ? b , c : d는 a ? (b, c) : d로서 해석되고, (a ? b), (c : d)로서 무의미하지 않다. 또한, 즉시, C 캐스트 표현식의 괄호묶지않은 결과는 sizeof의 피연산자가 될 수 없다는 것을 참고한다. 따라서, sizeof (int) * x는 (sizeof(int)) * x으로 해석되고 sizeof ((int) *x)가 아니다.
| 우선순위 | 연산자 | 설명 | 결합법칙 |
|---|---|---|---|
| 1 | :: |
범위 확인 (C++만) | 왼쪽에서 오른쪽 |
| 2 | ++ |
접미사 증가 | |
-- |
접미사 감소 | ||
() |
함수 호출 | ||
[] |
배열 첨자 | ||
. |
참조에 의한 요소 선택 | ||
-> |
포인터를 통해 요소 선택 | ||
typeid() |
런타임 형식 정보 (C++만) (typeid 참조) | ||
const_cast |
자료형 캐스트 (C++만) (const cast 참조) | ||
dynamic_cast |
자료형 캐스트 (C++만) (dynamic cast 참조) | ||
reinterpret_cast |
자료형 캐스트 (C++만) (reinterpret cast 참조) | ||
static_cast |
자료형 캐스트 (C++만) (static cast 참고) | ||
| 3 | ++ |
접두사 증가 | 오른쪽에서 왼쪽 |
-- |
접두사 감소 | ||
+ |
단항 덧셈 | ||
- |
단항 뺄셈 | ||
! |
논리적 NOT | ||
~ |
논리적 비트 NOT | ||
(자료형) |
자료형 캐스트 | ||
* |
우회 (역참조) | ||
& |
의-주소 | ||
sizeof |
의-크기 | ||
new, new[] |
동적 메모리 할당 (C++만) | ||
delete, delete[] |
동적 메모리 할당취소 (C++만) | ||
| 4 | .* |
멤버로의 포인터 (C++만) | 왼쪽에서 오른쪽 |
->* |
멤버로의 포인터 (C++만) | ||
| 5 | * |
곱셈 | |
/ |
나눗셈 | ||
% |
계수 (나머지) | ||
| 6 | + |
덧셈 | |
- |
뺄셈 | ||
| 7 | << |
비트 왼쪽 시프트 | |
>> |
비트 오른쪽 시프트 | ||
| 8 | < |
관계적 연산자들에 대해 < 각각의 | |
<= |
관계적 연산자들에 대해 ≤ 각각의 | ||
> |
관계적 연산자들에 대해 > 각각의 | ||
>= |
관계적 연산자들에 대해 ≥ 각각의 | ||
| 9 | == |
관계적 = 각각의 | |
!= |
관계적 ≠ 각각의 | ||
| 10 | & |
비트 AND | |
| 11 | ^ |
비트 XOR (배타적 or) | |
| 12 | | |
비트 OR (포함적 or) | |
| 13 | && |
논리 AND | |
| 14 | || |
논리 OR | |
| 15 | ?: |
삼중 조건부 (?: 참조) | 오른쪽에서 왼쪽 |
| 16 | = |
직접 할당 (C++ 클래스를 위해 기본적으로 제공됨) | |
+= |
덧셈에 의한 할당 | ||
-= |
뺄셈에 의한 할당 | ||
*= |
곱셈에 의한 할당 | ||
/= |
나눗셈에 의한 할당 | ||
%= |
나머지에 의한 할당 | ||
<<= |
비트 왼쪽 시프트에 의한 할당 | ||
>>= |
비트 오른쪽 시프트에 의한 할당 | ||
&= |
비트 AND에 의한 할당 | ||
^= |
비트 XOR에 의한 할당 | ||
|= |
비트 OR에 의한 할당 | ||
| 17 | throw |
던지기 연산자 (던지기 예외, C++만) | |
| 18 | , |
쉼표 | 왼쪽에서 오른쪽 |
참고 [편집]
우선순위 표는 명시적으로 괄호에 의해 지정되지 않을 때, 체인화된 표현식들에서 바인딩의 순서를 결정한다.
- 예를 들어,
++x*3은 약간의 우선순위 규칙(들)이 없어 모호하다. 우선순위 표는 우리에게 이것을 말해준다: x는 *하기보다 ++하기가 더 단단히 '제한'하고, 그래서 ++가 무엇을 하더라도 (지금 또는 나중—아래 참조), 그것은 오직 x하는 것을 한다 (그리고x*3하기가 아니다); 그것은 (++x,x*3)하기와 동일하다. - 마찬가지로,
3*x++와 함께, 후위 ++가 전체 표현식이 평가된 이후 작동이 설계되는 곳이지만, 우선순위 표는 오직 x가 증가되는 것을 명확하게 만든다 (그리고3*x가 아니다); 그것은 기능적으로 임시 값이 되는 tmp와 함께 (tmp=3*x,++x,tmp)와 같이 동일하다.
- 우선순위 또는 바인딩의 문제를 추상화한, 위의 도표를 고려한다. 컴파일러의 직업은 여러 y에게 바인딩으로 경쟁하는 단항 연산자들 ( 이것들을 3+( . ), 2*( . ), ( . )++ 그리고 ( . )[ i ] 이라고 부른다 )중 하나인, 표현식으로 도표를 해결하는 것이다. 우선순위 표의 순서는 각 행동에 대한 최종 하위-표현식들으로 해결된다: ( . )[ i ]은 오직 y에 대해 작동하고, ( . )++은 오직 y[i]에 대해 작동하고, 2*( . )은 오직 y[i]++에 대해 작동하고 3+( . )은 '오직' 2*((y[i])++)에 대해 작동한다. 어떤 하위 표현식이 우선순위 표에서 명확한 각 연산자에 의해서 작동되지만 각 연산자의 행위가 우선순위 표에 의해결되지 않을 때를 참고하는 것은 중요하다; 이 예제에서, ( . )++ 연산자는 오직 우선순위 규칙에 의해 y[i]에서 작동하지만 단독 바인딩 수준들은 접미사 ++의 타이밍을 표시하지 않는다 (( . )++ 연산자는 오직 y[i]이 표현식에서 평가된 후에 영향을 끼친다).
다중-문자 순서들을 포함하고 있는 연산자의 대부분은 각 문자의 연산자 이름에서 내장된 "이름"이 주어진다. 예를 들어, += 및 -=은 더 자세한 "덧셈에 의한 할당" 및 "뺄셈에 의한 할당" 대신에, 덧셈 등호(들) 및 뺄셈 등호(들)이라고 자주 부른다.
C와 C++에서의 연산자의 바인딩은 (해당 규칙에서)오히려 우선순위 표보다, 인수분해된 언어 문법에 의해 지정된다. 이것은 몇 가지 미묘한 갈등을 만든다. 예를 들어, C에서, 조건부 표현식에 대한 구문은:
논리적 OR 표현식 ? 표현식 : 조건부-표현
하지만 C++에서 그것은:
논리적 OR 표현식 ? 표현식 : 할당-표현
따라서 표현식:
e = a < d ? a++ : a = d
은 두 언어에서 다르게 분석되었다. C에서, 이 표현은 구문 오류이지만, 많은 컴파일러는 그것을 이와 같이 분석한다:
e = ((a < d ? a++ : a) = d)
lvalue가 아닌 조건 표현식(a++일 수 있다)의 결과 때문에, 이것은 의미론적 오류이다. C++에서, 그것은 이와 같이 분석한다:
e = (a < d ? a++ : (a = d))
그리고 그것은 올바른 표현식이다.
비트 논리 연산자의 우선순위는 비판되고 있다.[1] 개념적으로, &와 |은 +와 *같이 산술 연산자이다.
표현식 a & b == 7은 a & (b == 7)로 분석했던 반면 표현식 a + b == 7은 구문적으로 (a + b) == 7로 분석했다. 이것은 그들이 다른방법으로 했던 것보다 더 자주 사용되는 괄호가 필요하다.
C++ 연산자 동의어 [편집]
C++는 연산자들의 숫자에 대한 별명으로서 작동하는 키워드를 정의한다:[1] and (&&), bitand (&), and_eq (&=), or (||), bitor (|), or_eq (|=), xor (^), xor_eq (^=), not (!), not_eq (!=), compl (~). 그것들은 그들이 각 연산자의 이름 (문자 열)에 대한 간단한 텍스트 별명을 제외한, 다른 이름 아래에서 연산자가 같지 않음으로 그들이 대체하는 상징으로서 같은 방법을 정확하게 사용될 수 있다. 예를 들어, bitand는 비트 연산자뿐만 아니라 address-of 연산자를 대체하는 데 사용될 수 있고, 그것이 심지어 참조 자료형들을 지정하는 데 사용될 수 있다 (예. int bitand ref = n;).
ANSI C 사양은 헤더 파일 iso646.h에서 전처리 매크로로 이러한 키워드에 대한 허용을 만든다. C와의 호환성을 위해, C++는 헤더 ciso646을 제공하고, 그것의 포함은 효과가 없다.
참조 [편집]
- ↑ ISO/IEC JTC1/SC22/WG21 - C++ 표준 위원회 (1998년 9월 1일). 《ISO/IEC 14882:1998(E) 프로그래밍 언어 C++》. 프로그래밍 언어 C++에 대한 국제 표준화 작업 단체, 40–41쪽
