기타 연산자
프로그램에서 변수의 값을 변경하고, 특정 조건에 따라 간결하게 값을 결정하며, 메모리나 타입 정보를 얻는 등 다양한 상황에서 유용하게 사용되는 기타 연산자들에 대해 알아보겠습니다.
이 장에서는 대입 연산자, 복합 대입 연산자, 조건(삼항) 연산자, 크기 연산자(sizeof
), 주소 연산자(&
), 간접 참조 연산자(*
), 그리고 콤마 연산자(,
) 등 다양한 연산자들의 기능과 사용법을 상세히 살펴보겠습니다.
대입 연산자 (=
)
대입 연산자(=
) 는 오른쪽 피연산자의 값을 왼쪽 피연산자(변수)에 할당합니다.
가장 기본적인 연산자 중 하나이며, 변수의 값을 변경하거나 초기화할 때 사용됩니다.
int age = 20; // 20을 age 변수에 대입 (초기화)
age = 21; // 21을 age 변수에 대입 (값 변경)
double pi = 3.14;
char grade = 'A';
대입 연산은 오른쪽에서 왼쪽으로 진행됩니다.
대입 연산의 결과는 대입된 값 자체입니다.
이를 활용하여 여러 변수에 동시에 같은 값을 대입할 수 있습니다.
int x, y, z;
x = y = z = 10; // z에 10 대입, y에 z의 값(10) 대입, x에 y의 값(10) 대입
std::cout << "x: " << x << ", y: " << y << ", z: " << z << std::endl; // 출력: x: 10, y: 10, z: 10
복합 대입 연산자
복합 대입 연산자는 산술 연산, 비트 연산 등과 대입 연산을 결합한 형태입니다.
변수 = 변수 연산 값
형태의 코드를 변수 연산= 값
형태로 간결하게 줄여줍니다.
이는 코드의 가독성을 높이고, 컴파일러가 최적화를 수행하는 데 도움을 줄 수 있습니다.
연산자 | 예시 | 의미 |
---|---|---|
+= | a += b; | a = a + b; |
-= | a -= b; | a = a - b; |
*= | a *= b; | a = a * b; |
/= | a /= b; | a = a / b; |
%= | a %= b; | a = a % b; |
&= | a &= b; | a = a & b; |
|= | a |= b; | a = a | b; |
^= | a ^= b; | a = a ^ b; |
<<= | a <<= b; | a = a << b; |
>>= | a >>= b; | a = a >> b; |
#include <iostream>
int main() {
int score = 100;
score += 50; // score = score + 50; -> score는 150
std::cout << "score: " << score << std::endl;
double price = 100.0;
price *= 0.8; // price = price * 0.8; -> price는 80.0
std::cout << "price: " << price << std::endl;
int flags = 0b0010; // 십진수 2
flags |= 0b0100; // flags = flags | 0b0100; -> flags는 0b0110 (십진수 6)
std::cout << "flags: " << flags << std::endl;
return 0;
}
조건(삼항) 연산자 (? :
)
조건 연산자(Conditional Operator) 는 유일한 삼항(ternary) 연산자로, 세 개의 피연산자를 가집니다.
특정 조건에 따라 두 값 중 하나를 선택하는 데 사용됩니다. if-else
문을 간결하게 한 줄로 표현할 때 유용합니다.
조건 ? 표현식1 : 표현식2;
조건
이true
이면표현식1
이 평가되고 그 결과가 반환됩니다.조건
이false
이면표현식2
가 평가되고 그 결과가 반환됩니다.
#include <iostream>
#include <string>
int main() {
int age = 19;
std::string status = (age >= 18) ? "성인" : "미성년자";
std::cout << "당신은 " << status << "입니다." << std::endl; // 출력: 당신은 성인입니다.
int num1 = 10;
int num2 = 20;
int max_val = (num1 > num2) ? num1 : num2;
std::cout << "두 수 중 큰 값: " << max_val << std::endl; // 출력: 20
// 조건 연산자의 결과를 변수에 할당하지 않고 바로 사용할 수도 있습니다.
std::cout << "시험 결과: " << (85 >= 60 ? "합격" : "불합격") << std::endl; // 출력: 합격
return 0;
}
조건 연산자는 간결하지만 너무 복잡한 조건이나 표현식을 사용하면 가독성이 떨어질 수 있으므로 적절히 사용하는 것이 중요합니다.
크기 연산자 (sizeof
)
sizeof
연산자는 특정 데이터 타입 또는 변수가 메모리에서 차지하는 바이트(byte) 크기를 반환합니다.
컴파일 시점에 결정되며, 주로 메모리 관리가 중요한 시스템 프로그래밍이나 데이터 구조의 크기를 파악할 때 사용됩니다.
sizeof(타입_이름);
sizeof(변수_이름);
괄호를 생략할 수도 있지만, 타입을 인자로 사용할 때는 필수로 붙여야 합니다.
#include <iostream>
int main() {
int myInt;
double myDouble;
char myChar;
bool myBool;
std::cout << "int의 크기: " << sizeof(int) << " 바이트" << std::endl;
std::cout << "myInt 변수의 크기: " << sizeof(myInt) << " 바이트" << std::endl;
std::cout << "double의 크기: " << sizeof(double) << " 바이트" << std::endl;
std::cout << "myDouble 변수의 크기: " << sizeof(myDouble) << " 바이트" << std::endl;
std::cout << "char의 크기: " << sizeof(char) << " 바이트" << std::endl;
std::cout << "myChar 변수의 크기: " << sizeof(myChar) << " 바이트" << std::endl;
std::cout << "bool의 크기: " << sizeof(bool) << " 바이트" << std::endl;
std::cout << "myBool 변수의 크기: " << sizeof(myBool) << " 바이트" << std::endl;
// 배열의 크기
int numbers[5];
std::cout << "numbers 배열의 전체 크기: " << sizeof(numbers) << " 바이트" << std::endl; // 5 * sizeof(int)
std::cout << "numbers 배열의 요소 개수: " << sizeof(numbers) / sizeof(numbers[0]) << std::endl; // 배열 길이 계산
return 0;
}
sizeof
는 배열의 전체 크기를 구할 때 매우 유용하며, 이를 통해 배열의 요소 개수를 안전하게 계산할 수 있습니다.
주소 연산자 (&
)
주소 연산자(&
, Address-of Operator) 는 변수의 메모리 주소를 반환합니다.
이 연산자는 포인터(Pointer) 와 함께 사용됩니다.
포인터는 변수의 메모리 주소를 저장하는 특별한 타입의 변수입니다.
포인터에 대한 자세한 내용은 나중에 별도로 다시 다룰 것입니다.
&변수_이름;
#include <iostream>
int main() {
int value = 123;
double pi = 3.14;
std::cout << "value 변수의 값: " << value << std::endl;
std::cout << "value 변수의 메모리 주소: " << &value << std::endl; // 16진수 주소 출력
std::cout << "pi 변수의 값: " << pi << std::endl;
std::cout << "pi 변수의 메모리 주소: " << &pi << std::endl;
return 0;
}
출력되는 메모리 주소는 실행할 때마다 달라질 수 있으며, 16진수 형태로 표시됩니다.
간접 참조 연산자 (*
)
간접 참조 연산자(*
, Dereference Operator / Indirection Operator) 는 포인터 변수가 가리키는 메모리 주소에 저장된 실제 값에 접근할 때 사용됩니다.
역시 포인터 개념과 밀접하게 연관됩니다.
*포인터_변수;
#include <iostream>
int main() {
int data = 100;
int* ptr = &data; // ptr은 data의 메모리 주소를 저장하는 포인터 변수
std::cout << "data의 값: " << data << std::endl; // 출력: 100
std::cout << "ptr에 저장된 주소: " << ptr << std::endl; // data의 주소 출력
std::cout << "ptr이 가리키는 값: " << *ptr << std::endl; // 출력: 100 (*ptr은 data와 동일)
*ptr = 200; // ptr이 가리키는 메모리(즉, data)의 값을 200으로 변경
std::cout << "data의 새로운 값: " << data << std::endl; // 출력: 200
return 0;
}
*
기호는 포인터 변수를 선언할 때(int* ptr;
)는 '포인터 타입'임을 나타내고, 포인터 변수 앞에 사용될 때는 '간접 참조'를 나타내므로 혼동하지 않도록 주의해야 합니다.
콤마 연산자 (,
)
콤마 연산자(Comma Operator) 는 두 개 이상의 표현식을 순차적으로 평가하고, 가장 마지막 표현식의 결과를 반환합니다. 주로 for
반복문 헤더에서 여러 초기화나 증감식을 한 줄에 작성할 때 사용됩니다.
표현식1, 표현식2, 표현식3, ... , 마지막_표현식;
#include <iostream>
int main() {
int x = 10, y = 20; // 변수 선언 시 콤마 사용 (연산자 아님)
// 콤마 연산자 사용 (표현식)
int result = (x++, y += 5, x + y); // 1. x를 11로 증가, 2. y를 25로 증가, 3. (11 + 25) 계산
// 최종적으로 (x + y)의 결과인 36이 result에 대입
std::cout << "x: " << x << ", y: " << y << ", result: " << result << std::endl; // 출력: x: 11, y: 25, result: 36
// for 문에서 활용
for (int i = 0, j = 10; i < 5; ++i, --j) {
std::cout << "i: " << i << ", j: " << j << std::endl;
}
/* 출력:
i: 0, j: 10
i: 1, j: 9
i: 2, j: 8
i: 3, j: 7
i: 4, j: 6
*/
return 0;
}
콤마 연산자는 매우 낮은 우선순위를 가지므로, 다른 연산자와 함께 사용할 때는 괄호로 명확히 하는 것이 좋습니다.