Assignment operators
대입 및 복합 대입 연산자는 오른쪽의 값을 사용하여 왼쪽의 변수를 수정하는 이항 연산자입니다.
| 연산자 | 연산자 이름 | 예시 | 설명 | 동등 표현 |
|---|---|---|---|---|
| = | 기본 할당 | a = b | a 가 b 와 같아짐 | 해당 없음 |
| + = | 덧셈 할당 | a + = b | a 가 a 와 b 의 합과 같아짐 | a = a + b |
| - = | 뺄셈 할당 | a - = b | a 가 a 에서 b 를 뺀 값과 같아짐 | a = a - b |
| * = | 곱셈 할당 | a * = b | a 가 a 와 b 의 곱과 같아짐 | a = a * b |
| / = | 나눗셈 할당 | a / = b | a 가 a 를 b 로 나눈 값과 같아짐 | a = a / b |
| % = | 모듈로 할당 | a % = b | a 가 a 를 b 로 나눈 나머지와 같아짐 | a = a % b |
| & = | 비트 AND 할당 | a & = b | a 가 a 와 b 의 비트 AND와 같아짐 | a = a & b |
| | = | 비트 OR 할당 | a | = b | a 가 a 와 b 의 비트 OR와 같아짐 | a = a | b |
| ^ = | 비트 XOR 할당 | a ^ = b | a 가 a 와 b 의 비트 XOR와 같아짐 | a = a ^ b |
| <<= | 비트 왼쪽 시프트 할당 | a <<= b | a 가 a 를 b 만큼 왼쪽으로 시프트한 값과 같아짐 | a = a << b |
| >>= | 비트 오른쪽 시프트 할당 | a >>= b | a 가 a 를 b 만큼 오른쪽으로 시프트한 값과 같아짐 | a = a >> b |
목차 |
단순 할당
단순 대입 연산자 표현식의 형식은 다음과 같습니다.
lhs
=
rhs
|
|||||||||
여기서
| lhs | - | 수정 가능한 lvalue 표현식 (모든 완전한 객체 타입) |
| rhs | - | 모든 타입의 표현식 암시적으로 변환 가능 하거나 lhs 와 호환되는 타입 |
대입은 암시적 변환 을 통해 rhs 의 값을 lhs 의 타입으로 변환한 후, lhs 로 지정된 객체의 값을 rhs 의 변환된 값으로 대체합니다.
대입은 또한
lhs
에 저장된 값과 동일한 값을 반환합니다
(따라서
a
=
b
=
c
와 같은 표현이 가능합니다). 대입 연산자의
값 범주
는 비-좌측값입니다 (따라서
(
a
=
b
)
=
c
와 같은 표현은 유효하지 않습니다).
rhs 와 lhs 는 다음 중 하나를 충족해야 합니다:
- lhs 와 rhs 모두 호환되는 struct 또는 union 타입을 가지고 있거나, 또는..
- rhs 는 lhs 로 암시적으로 변환 가능 해야 하며, 이는 다음을 의미합니다
-
- lhs 와 rhs 모두 산술 타입 을 가지는 경우, 이때 lhs 는 volatile 한정자를 가질 수 있음 또는 atomic (C11부터)
- lhs 와 rhs 모두 포인터 타입이며 호환되는 (한정자는 무시) 타입을 가리키거나, 한쪽 포인터가 void 포인터이며 변환 이 가리키는 타입에 한정자를 추가하지 않는 경우. lhs 는 volatile 또는 restrict (C99부터) 한정자를 가질 수 있음 또는 atomic (C11부터) .
- lhs 가 (한정자가 있을 수 있는 또는 atomic (C11부터) ) 포인터이고 rhs 가 NULL 과 같은 null 포인터 상수인 경우 또는 nullptr_t 값인 경우 (C23부터)
|
(C99부터) |
| (C23부터) |
참고 사항
만약 rhs 와 lhs 가 메모리에서 겹치는 경우(예: 동일한 union의 멤버인 경우), 겹침이 정확하고 타입이 호환 가능한 경우를 제외하고는 동작이 정의되지 않습니다.
배열은 할당 가능하지 않지만, 구조체로 감싸진 배열은 동일한(또는 호환되는) 구조체 타입의 다른 객체에 할당 가능합니다.
lhs 를 갱신하는 부수 효과는 sequenced after 값 계산 이후에 발생하지만, lhs 와 rhs 자체의 부수 효과는 그렇지 않으며, 피연산자들의 평가는 상대적으로 비순서화되어 있습니다 (따라서 i = ++ i ;와 같은 표현식은 정의되지 않습니다)
대입은 부동 소수점 표현식에서 추가 범위와 정밀도를 제거합니다(참조 FLT_EVAL_METHOD ).
C++에서 할당 연산자는 좌측값 표현식이지만, C에서는 그렇지 않습니다.
#include <stdio.h> int main(void) { // 정수 int i = 1, j = 2, k = 3; // 초기화, 대입이 아님 i = j = k; // i와 j의 값은 이제 3 // (i = j) = k; // 오류: lvalue 필요 printf("%d %d %d\n", i, j, k); // 포인터 const char c = 'A'; // 초기화; 대입이 아님 const char *p = &c; // 초기화; 대입이 아님 const char **cpp = &p; // 초기화; 대입이 아님 // cpp = &p; // 오류: char**는 const char**로 변환 불가 *cpp = &c; // OK, char*는 const char*로 변환 가능 printf("%c \n", **cpp); cpp = 0; // OK, 널 포인터 상수는 어떤 포인터로든 변환 가능 // 배열 int arr1[2] = {1,2}, arr2[2] = {3, 4}; // arr1 = arr2; // 오류: 배열에 대입할 수 없음 printf("arr1[0]=%d arr1[1]=%d arr2[0]=%d arr2[1]=%d\n", arr1[0], arr1[1], arr2[0], arr2[1]); struct { int arr[2]; } sam1 = { {5, 6} }, sam2 = { {7, 8} }; sam1 = sam2; // OK: 구조체로 감싼 배열은 대입 가능 printf("%d %d \n", sam1.arr[0], sam1.arr[1]); }
출력:
3 3 3 A arr1[0]=1 arr1[1]=2 arr2[0]=3 arr2[1]=4 7 8
복합 할당
복합 할당 연산자 표현식의 형식은 다음과 같습니다
| lhs op rhs | |||||||||
여기서
| op | - | 다음 중 하나 * = , / = % = , + = - = , <<= , >>= , & = , ^ = , | = |
| lhs , rhs | - | 산술 타입 을 가지는 표현식들 (단, lhs 는 한정되거나 atomic일 수 있음). 단, op 가 + = 또는 - = 인 경우, +와 - 연산자와 동일한 제한 조건으로 포인터 타입도 허용됨 |
표현식
lhs
@=
rhs
는
lhs
=
lhs
@
(
rhs
)
와 정확히 동일하며, 단지
lhs
가 한 번만 평가된다는 점만 다릅니다.
|
만약 lhs 가 atomic 타입을 가지고 있다면, 이 연산은 memory_order_seq_cst 메모리 순서를 가진 단일 atomic 읽기-수정-쓰기 연산으로 동작합니다. 정수 atomic 타입의 경우, 복합 할당 @ = 는 다음과 동일합니다: T1* addr = &lhs; T2 val = rhs; T1 old = *addr; T1 new; do { new = old @ val } while (!atomic_compare_exchange_strong(addr, &old, new); |
(C11부터) |
출력:
10 100 10 50 10 1000 1 0
참고문헌
- C17 표준 (ISO/IEC 9899:2018):
-
- 6.5.16 대입 연산자 (p: 72-73)
- C11 표준 (ISO/IEC 9899:2011):
-
- 6.5.16 대입 연산자 (p: 101-104)
- C99 표준 (ISO/IEC 9899:1999):
-
- 6.5.16 대입 연산자 (p: 91-93)
- C89/C90 표준 (ISO/IEC 9899:1990):
-
- 3.3.16 Assignment operators
참고 항목
| 일반 연산자 | ||||||
|---|---|---|---|---|---|---|
| 대입 |
증가
감소 |
산술 | 논리 | 비교 |
멤버
접근 |
기타 |
|
a
=
b
|
++
a
|
+
a
|
!
a
|
a
==
b
|
a
[
b
]
|
a
(
...
)
|
참고 항목
|
C++ 문서
에 대한
대입 연산자
|