Namespaces
Variants

Other operators

From cppreference.net

다른 주요 카테고리에 속하지 않는 연산자들의 모음입니다.

연산자 연산자 이름 예시 설명
( ... ) 함수 호출 f ( ... ) 함수 f ()를 0개 이상의 인수로 호출
, 쉼표 연산자 a, b 표현식 a 를 평가하고 반환값을 무시한 후 모든 부수 효과를 완료한 다음, 표현식 b 를 평가하여 이 평가의 타입과 결과를 반환
( type ) 타입 변환 ( type ) a a 의 타입을 type 으로 변환
? : 조건 연산자 a ? b : c a 가 논리적으로 참(0으로 평가되지 않음)이면 표현식 b 를 평가하고, 그렇지 않으면 표현식 c 를 평가
sizeof sizeof 연산자 sizeof a a 의 바이트 단위 크기
_Alignof
(C11부터)
_Alignof 연산자 _Alignof ( type ) type 에 필요한 정렬 요구사항
typeof typeof 연산자 typeof ( a ) a 의 타입

목차

함수 호출

함수 호출 표현식의 형식은 다음과 같습니다

표현식 ( 인수-목록  (선택사항) )

여기서

expression - 함수 포인터 타입의 임의의 표현식( lvalue conversions 이후)
argument-list - 모든 완전한 객체 타입의 표현식들로 구성된 쉼표로 구분된 목록(쉼표 연산자는 사용할 수 없음). 인수를 받지 않는 함수를 호출할 때는 생략할 수 있습니다.

함수 호출 표현식의 동작은 호출되는 함수의 프로토타입이 호출 지점에서 범위 내 에 있는지 여부에 따라 달라집니다.

프로토타입이 있는 함수 호출

1) 매개변수의 개수는 인수의 개수와 동일해야 합니다(생략 부호 매개변수를 사용하는 경우는 제외).
2) 각 매개변수의 타입은 해당 인수의 한정되지 않은 타입을 매개변수의 타입으로 변환하는 할당에 의한 암시적 변환 이 존재하는 타입이어야 합니다.
또한, 배열 타입 의 모든 매개변수에 대해 static 키워드가 [ ] 사이에 사용되는 경우, 인수 표현식은 매개변수의 크기 표현식에 지정된 요소 수 이상을 가진 배열의 요소를 가리키는 포인터를 지정해야 합니다.
(C99부터)
4) Assignment 는 각 인수의 값을 해당 함수 매개변수에 복사하기 위해 수행되며, 매개변수 타입과 그 재귀적 요소 또는 멤버(있는 경우)에 대한 모든 타입 한정자는 무시됩니다(참고: 함수는 매개변수를 수정할 수 있으며, 이러한 변경은 인수에 영향을 주지 않습니다; C 함수 호출은 값에 의한 호출만 가능합니다).
5) 함수가 실행되고, 함수가 반환하는 값이 함수 호출 표현식의 값이 됩니다 (함수가 void를 반환하는 경우, 함수 호출 표현식은 void 표현식입니다)
void f(char* p, int x) {}
int main(void)
{
    f("abc", 3.14); // array to pointer and float to int conversions
}

프로토타입 없는 함수 호출

2) 기본 인수 승격 이 모든 인수 표현식에 수행됨.
3) 대입 이 각 인수의 값을 해당 함수 매개변수에 복사하기 위해 수행되며, 매개변수 타입과 그 재귀적 요소 또는 멤버(있는 경우)의 모든 타입 한정자는 무시됨.
4) 함수가 실행되고, 반환된 값이 함수 호출 표현식의 값이 됨 (함수가 void를 반환하면 함수 호출 표현식은 void 표현식임)
void f(); // no prototype
int main(void)
{
    f(1, 1.0f); // UB unless f is defined to take an int and a double
}
void f(int a, double c) {}

프로토타입 없는 함수 호출의 동작은 다음 경우에 정의되지 않음:

  • 인수의 개수가 매개변수의 개수와 일치하지 않는 경우
  • 인수의 승격된 타입들이 매개변수의 승격된 타입들과 호환되지 않는 경우. 단 다음은 예외:
  • 동일한 정수 타입의 signed와 unsigned 버전은 인수 값이 두 타입 모두로 표현 가능한 경우 호환되는 것으로 간주됨
  • void 포인터와 (cvr-qualified 가능성이 있는) 문자 타입 포인터는 호환되는 것으로 간주됨
(C23까지)

참고 사항

함수 호출 대상 함수를 지정하는 expression 및 모든 인자들의 평가는 서로 간에 unsequenced 입니다 (그러나 함수 본문 실행 시작 전에 sequence point가 존재합니다)

(*pf[f1()]) (f2(), f3() + f4()); // f1, f2, f3, f4는 임의의 순서로 호출될 수 있음

함수 호출은 함수 포인터에 대해서만 정의되어 있지만, 함수-포인터 암시적 변환 으로 인해 함수 지정자와도 동작합니다.

int f(void) { return 1; }
int (*pf)(void) = f;
int main(void)
{
    f();    // f를 포인터로 변환한 후 호출
    (&f)(); // 함수 포인터를 생성한 후 호출
    pf();    // 함수 호출
    (*pf)(); // 함수 지정자를 얻어 포인터로 변환한 후 호출
    (****f)(); // 포인터로 변환, 함수 획득을 4회 반복한 후 호출
    (****pf)(); // 또한 유효함
}

사용되지 않는 인수를 무시하는 함수들, 예를 들어 printf 와 같은 함수들은 정의되지 않은 동작을 유발하지 않기 위해 반드시 프로토타입이 있는 범위 내에서 호출되어야 합니다(이러한 함수들의 프로토타입은 반드시 후행 생략 부호 매개변수를 사용합니다).

함수 매개변수의 의미론을 현재 표준으로 기술한 방식은 결함이 있습니다. 매개변수가 호출 시 인수로부터 할당된다고 명시하고 있기 때문인데, 이는 const 한정 매개변수나 멤버 타입을 부정확하게 거부하며, 많은 플랫폼에서 함수 매개변수에 대해 구현 불가능한 volatile의 의미론을 부적절하게 적용합니다. C11 이후의 결함 보고서 DR427 에서는 이러한 의미론을 할당에서 초기화로 변경하는 것을 제안했으나, 결함이 아니라는 이유로 종결되었습니다.

expression 이 완전히 식별자로만 구성되고 해당 식별자가 선언되지 않은 함수 호출 표현식은 다음과 같이 식별자가 선언된 것처럼 동작합니다.

extern int identifier(); // returns int and has no prototype

따라서 다음 완전한 프로그램은 유효한 C89입니다:

main()
{
    int n = atoi("123"); // implicitly declares atoi as int atoi()
}
(C99까지)

콤마 연산자

쉼표 연산자 표현식의 형식은 다음과 같습니다

lhs , rhs

여기서

lhs - 임의의 표현식
rhs - 다른 콤마 연산자를 제외한 임의의 표현식 (다시 말해, 콤마 연산자의 결합 방향 은 좌측에서 우측으로)

먼저, 왼쪽 피연산자인 lhs 가 평가되고 그 결과 값은 버려집니다.

그런 다음, 시퀀스 포인트 가 발생하여 lhs 의 모든 부수 효과가 완료됩니다.

그런 다음, 오른쪽 피연산자인 rhs 가 평가되고 그 결과가 콤마 연산자에 의해 비-좌측값 으로 반환됩니다.

참고 사항

lhs 의 타입은 void 일 수 있습니다(즉, void 를 반환하는 함수 호출이거나, cast 표현식이 void 로 변환된 경우일 수 있습니다)

콤마 연산자는 C++에서는 lvalue일 수 있지만, C에서는 절대 그렇지 않습니다

쉼표 연산자는 구조체를 반환할 수 있습니다 (구조체를 반환하는 다른 표현식으로는 복합 리터럴, 함수 호출, 대입 연산, 조건 연산자가 있습니다)

다음 상황에서는 쉼표가 다른 의미를 가지기 때문에 쉼표 연산자가 표현식의 최상위 수준에 나타날 수 없습니다:

콤마 연산자를 이러한 맥락에서 사용해야 하는 경우, 반드시 괄호로 묶어야 합니다:

// int n = 2,3; // 오류: 쉼표가 다음 선언자의 시작으로 간주됨
// int a[2] = {1,2,3}; // 오류: 요소 수보다 초기화자가 더 많음
int n = (2,3), a[2] = {(1,2),3}; // 정상
f(a, (t=3, t+2), c); // 정상, 먼저 t에 3을 저장한 다음 세 개의 인수로 f를 호출함

최상위 쉼표 연산자는 배열 경계에서도 허용되지 않습니다

// int a[2,3]; // 오류
int a[(2,3)]; // OK, 크기 3의 VLA 배열 (VLA인 이유: (2,3)이 상수 표현식이 아니기 때문)

콤마 연산자는 최상위 수준인지 여부와 관계없이 상수 표현식 에서 허용되지 않습니다

// static int n = (1,2); // 오류: 상수 표현식에서 쉼표 연산자를 호출할 수 없음

캐스트 연산자

참조 cast operator

조건 연산자

조건부 연산자 표현식의 형식은 다음과 같습니다

조건 ? 참-표현식 : 거짓-표현식

여기서

condition - 스칼라 타입의 표현식
expression-true - condition이 0과 비교하여 같지 않을 경우 평가될 표현식
expression-false - condition이 0과 비교하여 같을 경우 평가될 표현식

다음 표현식들만 expression-true expression-false 로 허용됩니다

(C23부터)
  • 한 식은 포인터이고 다른 식은 널 포인터 상수(예: NULL ) 또는 nullptr_t (C23 이후)
  • 한 식은 객체에 대한 포인터이고 다른 식은 void에 대한 포인터(한정자 있을 수 있음)인 경우
1) 먼저 condition 을 평가합니다. 이 평가 이후에는 sequence point 가 존재합니다.
2) condition 의 결과가 0과 비교하여 같지 않으면 expression-true 를 실행하고, 그렇지 않으면 expression-false 를 실행합니다.
3) 평가 결과를 다음과 같이 정의된 공통 타입 으로 변환 을 수행합니다:
1) 표현식이 산술 타입을 가지는 경우, 공통 타입은 usual arithmetic conversions 이후의 타입입니다
2) 표현식이 struct/union 타입을 가지는 경우, 공통 타입은 해당 struct/union 타입입니다
3) 두 표현식이 모두 void인 경우, 전체 조건부 연산자 표현식은 void 표현식입니다
4) 하나가 포인터이고 다른 하나가 널 포인터 상수 또는 nullptr_t (C23부터) 인 경우, 타입은 해당 포인터의 타입입니다
5) 둘 다 포인터인 경우, 결과는 두 대상 타입의 cvr 한정자를 모두 결합한 타입에 대한 포인터입니다 (즉, 하나가 const int * 이고 다른 하나가 volatile int * 인 경우, 결과는 const volatile int * 임). 그리고 타입들이 서로 다른 경우, 대상 타입은 복합 타입 입니다.
6) 하나가 void 포인터인 경우, 결과는 결합된 cvr 한정자를 가진 void 포인터입니다
7) 둘 다 nullptr_t 타입을 가질 경우, 공통 타입 역시 nullptr_t 입니다
(C23부터)
#define ICE(x) (sizeof(*(1 ? ((void*)((x) * 0l)) : (int*)1)))
// x가 정수 상수 표현식이면 매크로는 다음으로 확장됩니다
sizeof(*(1 ? NULL : (int *) 1))  // (void *)((x)*0l)) -> NULL
// 포인트 (4)에 따라 이것은 더 나아가 다음으로 변환됩니다
sizeof(int)
// x가 정수 상수 표현식이 아니면 매크로는 다음으로 확장됩니다
// 포인트 (6)에 따라
(sizeof(*(void *)(x))           // 불완전한 타입으로 인한 오류

참고 사항

조건 연산자는 절대 lvalue 표현식 이 아니지만, 구조체/공용체 타입의 객체를 반환할 수 있습니다. 구조체를 반환할 수 있는 다른 표현식으로는 대입 , 콤마 , 함수 호출 , 그리고 복합 리터럴 이 있습니다.

C++에서는 lvalue 표현식일 수 있습니다.

자세한 내용은 이 연산자와 대입 연산자의 상대적 우선순위에 대해 연산자 우선순위 를 참조하십시오.

조건부 연산자는 오른쪽에서 왼쪽으로의 결합성을 가지며, 이를 통해 연쇄 사용이 가능합니다

#include <assert.h>
enum vehicle { bus, airplane, train, car, horse, feet };
enum vehicle choose(char arg)
{
    return arg == 'B' ? bus      :
           arg == 'A' ? airplane :
           arg == 'T' ? train    :
           arg == 'C' ? car      :
           arg == 'H' ? horse    :
                        feet     ;
}
int main(void)
{
    assert(choose('H') == horse && choose('F') == feet);
}

sizeof 연산자

참조 sizeof 연산자

_Alignof 연산자

참조 _Alignof 연산자

typeof 연산자

참조 typeof 연산자

참고문헌

  • C23 표준 (ISO/IEC 9899:2024):
  • 6.5.2.2 함수 호출 (p: TBD)
  • 6.5.3.4 sizeof 및 _Alignof 연산자 (p: TBD)
  • 6.5.4 캐스트 연산자 (p: TBD)
  • 6.5.15 조건 연산자 (p: TBD)
  • 6.5.17 쉼표 연산자 (p: TBD)
  • 6.7.3.5 Typeof 지정자 (p: 115-118)
  • C17 표준 (ISO/IEC 9899:2018):
  • 6.5.2.2 함수 호출 (p: 58-59)
  • 6.5.3.4 sizeof 및 _Alignof 연산자 (p: 64-65)
  • 6.5.4 캐스트 연산자 (p: 65-66)
  • 6.5.15 조건 연산자 (p: 71-72)
  • 6.5.17 쉼표 연산자 (p: 75)
  • C11 표준 (ISO/IEC 9899:2011):
  • 6.5.2.2 함수 호출 (p: 81-82)
  • 6.5.3.4 sizeof 및 _Alignof 연산자 (p: 90-91)
  • 6.5.4 캐스트 연산자 (p: 91)
  • 6.5.15 조건 연산자 (p: 100)
  • 6.5.17 쉼표 연산자 (p: 105)
  • C99 표준 (ISO/IEC 9899:1999):
  • 6.5.2.2 함수 호출 (p: 71-72)
  • 6.5.3.4 sizeof 연산자 (p: 80-81)
  • 6.5.4 캐스트 연산자 (p: 81)
  • 6.5.15 조건 연산자 (p: 90-91)
  • 6.5.17 콤마 연산자 (p: 94)
  • C89/C90 표준 (ISO/IEC 9899:1990):
  • 3.3.2.2 함수 호출
  • 3.3.3.4 sizeof 연산자
  • 3.3.4 캐스트 연산자
  • 3.3.15 조건 연산자
  • 3.3.17 쉼표 연산자

참고 항목

일반 연산자
대입 증가
감소
산술 논리 비교 멤버
접근
기타

a = b
a + = b
a - = b
a * = b
a / = b
a % = b
a & = b
a | = b
a ^ = b
a <<= b
a >>= b

++ a
-- a
a ++
a --

+ a
- a
a + b
a - b
a * b
a / b
a % b
~a
a & b
a | b
a ^ b
a << b
a >> b

! a
a && b
a || b

a == b
a ! = b
a < b
a > b
a <= b
a >= b

a [ b ]
* a
& a
a - > b
a. b

a ( ... )
a, b
( type ) a
a ? b : c
sizeof


_Alignof
(C11부터)
(C23 이전)

alignof
(C23부터)

C++ 문서 for Other operators