C와 C++의 연산자

위키백과, 우리 모두의 백과사전.

이것은 CC++ 프로그래밍 언어연산자의 목록이다. 나열된 모든 연산자는 C++에 존재한다. 네번째 열("C에 포함됨")은 해당 연산자가 C에 존재하는지를 표시한다. C는 연산자 오버로딩을 지원하지 않는다.

연산자가 오버로드되지 않았다면, &&, ||, ,(쉼표 연산자) 연산자는 첫 번째 피연산자(operand)가 평가된 시점이 시퀀스 포인트이다.

C++는 형 변환 연산자인 const_cast, static_cast, dynamic_cast, reinterpret_cast를 포함한다. 이들 연산자의 서식은 우선순위 단계가 중요하지 않다는 것을 의미한다.

C와 C++에서 사용 가능한 연산자 중 대부분은 C#, 자바, , 그리고 PHP와 같은 다른 언어에서도 동일한 우선순위, 결합법칙, 의미론으로 사용가능하다.

연산자 표[편집]

이 표에서 a, b, c는 경우에 따라 유효한 값(리터럴, 변수 값, 반환 값), 개체 이름, 왼쪽 값(lvalue)을 나타낸다. R, S, T는 자료형을 나타내고 K는 클래스나 열거형을 나타낸다.

산술 연산자[편집]

연산자 이름 구문 오버로드 가능[참고 1] C에 포함됨[참고 2]
T의 멤버로서 외부 클래스 정의들
대입 a = b T& T::operator=(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+() 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);[참고 3] T operator++(T& a, int);[참고 3]
감소 전위 --a T& T::operator--(); T& operator--(T& a);
후위 a-- T T::operator--(int);[참고 3] T operator--(T& a, int);[참고 3]

비교 연산자/관계 연산자[편집]

연산자 이름 구문 오버로드
가능[참고 1]
C에서
포함됨[참고 2]
프로토타입 예제
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);
삼단 비교[1] a <=> b 아니요 auto T::operator<=>(const T& b) const; auto T::operator<=>(const T& a, const T& b);

논리 연산자[편집]

연산자
이름
구문 오버로드
가능[참고 1]
C에서
포함됨[참고 2]
프로토타입 예제
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);

연산자 && 와 || 그리고 , 는 오버로딩하지 말아야 한다.[2] 논리 연산이 필요하다면 대신 operator bool () 을 쓰도록 하자.

비트 연산자[편집]

연산자
이름
구문 오버로드 가능[참고 1] C에서 포함됨[참고 2] 프로토타입 예제
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);
비트
왼쪽
시프트[참고 4]
a << b T T::operator<<(const T& b) const; T operator<<(const T& a, const T& b);
비트
오른쪽
시프트[참고 4]
a >> b T T::operator>>(const T& b) const; T operator>>(const T& a, const T& b);

복합 할당 연산자[편집]

연산자 이름 구문 오버로드 가능[참고 1] C에서 포함됨[참고 2] 프로토타입 예제
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);

멤버와 포인터 연산자[편집]

연산자 이름 구문 오버로드 가능[참고 1] C에서 포함됨[참고 2] 프로토타입 예제[참고 5]
T의 멤버로서 외부 클래스 정의들
포인터 배열 a[b] R& T::operator[](const T2& b);
빈칸
포인터[참고 6] *a R& T::operator*(); R& operator*(T& a);
참조[참고 7] &a T* T::operator&(); T* operator&(T& a);
포인터 a에 할당된 객체의 멤버 b a->b R* T::operator->();
빈칸
객체 a의 멤버 b a.b 아니요 빈칸
포인터 a에 할당된 객체의 멤버
b에 할당된 멤버[참고 8]
a->*b 아니요 R T::operator->*(R);[참고 9] R operator->*(T, R);[참고 9]
객체 ab에 할당된 멤버 a.*b 아니요 아니요 빈칸

기타 연산자[편집]

연산자
이름
구문 오버로드
가능[참고 1]
C에서
포함됨[참고 2]
프로토타입 예제[참고 10]
T의 멤버로서 외부 클래스 정의들
함수 호출
[참고 11]
a(a1, a2) R T::operator()(Arg1 a1, Arg2 a2, );[참고 12] 빈칸
쉼표 a, b R& T::operator,(R& b) const; R& operator,(const T& a, R& b);
삼항
연산자
a ? b : c 아니요 빈칸
범위 확인 a::b 아니요 아니요 빈칸
Size-of sizeof(a)[참고 13]
sizeof(자료형)
아니요 빈칸
자료형
식별
typeid(a)
typeid(자료형)
아니요 아니요 빈칸
캐스트 (자료형) a T::operatorR() const;[참고 14] 빈칸
저장소
할당
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);

연산자 우선순위[편집]

다음은 CC++ 언어에서 모든 연산자의 우선순위결합법칙을 나열하는 표이다[참고 15]. 연산자는 내림차순 우선순위에서, 위에서 아래로 나열된다. 우선순위 내림차순은 연산자와 피연산자를 묶는 행위의 우선순서를 나타낸다. 표현식을 고려해서, 어떤 행 위에 나열된 연산자는 그것의 더 아래쪽 행 위에 나열된 모든 연산자의 이전에 피연산자와 묶인다. 같은 셀에 있는 연산자[참고 16]는 주어진 결합법칙의 방향대로 피연산자와 묶인다. 연산자의 우선순위는 오버로딩에 의해 영향받지 않는다. 연산자의 피연산자들이 모두 평가된 후에 그 연산자로 결과값이 계산되는 순서로 평가된다.

C와 C++에서 표현식의 구문은 문맥 자유 문법에 의해 지정된다.[출처 필요] 여기에 주어진 표는 문법으로부터 추론되었다.[출처 필요] ISO C 1999년 표준에 대해, 항목 6.5.6 주 71은 C 연산자의 우선순위를 정의하는 사양에 의해 제공되는 C 문법을 정하고, 또한 사양의 항목 순서를 밀접하게 따라가는 문법으로 인한 연산자 우선순위를 정한다:

[C] 구문 [즉, 문법]은 첫 번째 가장높은 우선순위, 하위조항의 주요 하위조항의 순서와 동일한, 표현식의 평가에서 연산자 우선순위를 지정한다.

우선순위 표는, 대부분 적절하지만, 몇 가지 세부 정보를 해결할 수 없다. 특히, 3항 연산자는 그것의 중간 피연산자로서 어떤 임의의 표현식을 허용함에도 불구하고, 할당 및 쉼표 연산자보다 높은 우선순위가 있는 것으로서 나열된다는 것을 참고한다. 그러므로 a ? b , c : da ? (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 == 관계적 = 각각의
!= 관계적 ≠ 각각의
11 & 비트 AND
12 ^ 비트 XOR (배타적 or)
13 | 비트 OR (포함적 or)
14 && 논리 AND
15 || 논리 OR
16 ?: 3항 연산자 조건부 (?: 참조) 오른쪽에서 왼쪽
17 = 직접 할당 (C++ 클래스를 위해 기본적으로 제공됨)
+= 덧셈에 의한 할당
-= 뺄셈에 의한 할당
*= 곱셈에 의한 할당
/= 나눗셈에 의한 할당
%= 나머지에 의한 할당
<<= 비트 왼쪽 시프트에 의한 할당
>>= 비트 오른쪽 시프트에 의한 할당
&= 비트 AND에 의한 할당
^= 비트 XOR에 의한 할당
|= 비트 OR에 의한 할당
18 throw 던지기 연산자 (던지기 예외, C++만)
19 , 쉼표 왼쪽에서 오른쪽

참고 사항[편집]

우선순위 표는 명시적으로 괄호에 의해 지정되지 않을 때, 체인화된 표현식들에서 바인딩의 순서를 결정한다.

  • 예를 들어, ++x*3은 얼핏 보면 모호해 보이지만, 우선순위 표에 따르면 x*연산자보다 전위 ++연산자를 더 우선시하고, 따라서 ++x 연산을 수행한 후에 x*3 연산을 수행하게 된다.
  • 3*x++도 마찬가지로, 후위 ++연산자가 가장 나중에 실행될 것처럼 보이지만, 우선순위에 따라 x++ 연산을 먼저 수행하게 된다. 그러나 x++ 연산은 후위 연산자라서 변수의 값을 사용 후에 증가시키므로, 결국 출력값은 x*3으로 출력이 된 후에, x값이 증가한다.
우선순위 및 바인딩
  • 우선순위 또는 바인딩의 문제를 추상화한, 오른쪽 그림을 보자. 컴파일러의 직업은 여러 y에게 바인딩으로 경쟁하는 단항 연산자들[참고 17]중 하나인, 표현식으로 도표를 해결하는 것이다. 우선순위 표의 순서는 각 행동에 대한 최종 하위-표현식들로 해결된다: ( . )[ i ]은 오직 y에 대해 작동하고, ( . )++은 오직 y[i]에 대해 작동하고, 2*( . )은 오직 y[i]++에 대해 작동하고 3+( . )은 '오직' 2*((y[i])++)에 대해 작동한다. 어떤 하위 표현식이 우선순위 표에서 명확한 각 연산자에 의해서 작동되지만 각 연산자의 행위가 우선순위 표에 의해결되지 않을 때를 참고하는 것은 중요하다; 이 예제에서, ( . )++ 연산자는 오직 우선순위 규칙에 의해 y[i]에서 작동하지만 단독 바인딩 수준들은 후위 연산자 ++의 타이밍을 표시하지 않는다[참고 18].

다중-문자 순서들을 포함하고 있는 연산자의 대부분은 각 문자의 연산자 이름에서 내장된 "이름"이 주어진다. 예를 들어, +=-=은 더 자세한 "덧셈에 의한 할당" 및 "뺄셈에 의한 할당" 대신에, '덧셈 등호(들)' 및 '뺄셈 등호(들)'이라고 자주 부른다.

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)) 그리고 그것은 올바른 표현식이다.

비트 논리 연산자의 우선순위는 비판받고 있다.[3] 개념적으로, &|+*같이 산술 연산자이다.

표현식 a & b == 7a & (b == 7)로 분석했던 반면 표현식 a + b == 7은 구문적으로 (a + b) == 7로 분석했다. 이것은 그들이 다른방법으로 했던 것보다 더 자주 사용되는 괄호가 필요하다.

C++ 연산자 동의어[편집]

C++는 연산자들의 숫자에 대한 별명으로서 작동하는 키워드를 정의한다:[4] 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을 제공하고, 또한#include<ciso646.h>는 효과가 없다.

참고 문헌 및 각주[편집]

  • Dodrill, Gordon (1992년 1월 20일). 《C++ Tutor》. Coronado Enterprises. 2008년 8월 21일에 원본 문서에서 보존된 문서. 2010년 3월 8일에 확인함. 
  1. C++20 표준
  2. scott meyers. 《More Effective C++ item 7》. addison wesley. 
  3. “보관된 사본”. 2013년 6월 22일에 원본 문서에서 보존된 문서. 2011년 10월 4일에 확인함. 
  4. ISO/IEC JTC1/SC22/WG21 - C++ 표준 위원회 (1998년 9월 1일). 《ISO/IEC 14882:1998(E) 프로그래밍 언어 C++》. 프로그래밍 언어 C++에 대한 국제 표준화 작업 단체. 40–41쪽. 

주해[편집]

  1. 연산자가 C++에서 오버로드 가능한(overloadable) 것을 의미한다.
  2. C에서 연산자가 있고 의미론적 의미를 가지는 것을 의미한다.(C는 연산자 오버로딩을 지원하지 않는다.)
  3. C++는 전위 및 후위 사이의 증가 연산자를 구별하는 이름없는 더미 매개변수 int를 사용한다.
  4. iostream의 문맥에서, 저자는 각각, “put-to” 또는 "스트림 삽입" 및 “get-from” 또는 "스트림 추출" 연산자로서 <<>>를 자주 참조할 것이다.
  5. T, T2 및 R은 모든 자료형이다.
  6. 주소 a에 할당된 객체
  7. a객체의 원본
  8. 예제는 스캇 마이어스의 "스마트 포인터를 위한 ->* 연산자 구현하기"에서 찾을 수 있다.
  9. ->* 연산자가 있는 곳의 경우에는 기본적 구현처럼 작동하고, R 매개변수는 클래스 T의 메서드에서 메서드 포인터가 될 것이고 반환 값은 메서드 매개변수와 함께(오직) 호출될 것을 준비하는 함수 개체의 몇몇 종류가 될 것이다.
  10. T, R, Arg1 및 Arg2는 모든 자료형이다.
  11. 함수 개체를 살펴본다.
  12. Overload may accept zero or more arguments.
  13. 괄호들은 자료형의 크기를 받을 때에만, 값의 크기를 받을 때는 필요하지 않다. 그러나, 그들은 보통 관계없이 사용된다.
  14. 사용자 정의 변환에 대해, 반환 자료형은 절대적 및 필연적으로 연산자 이름과 일치한다.
  15. 연산자는 또한 자바, , PHP 및 많은 다른 최근 언어가 존재할 때, 우선순위는 그 주어진 것과 동일하다[출처 필요].
  16. 여기는 셀에 나열된 연산자의 여러 행이 될 수 있다
  17. 이것들을 3+( . ), 2*( . ), ( . )++, ( . )[ i ]이라고 부른다.
  18. ( . )++ 연산자는 오직 y[i]이 표현식에서 평가된 후에 영향을 끼친다.

외부 링크[편집]