1. 산술 연산자
숫자 형식의 데이터에 사용 가능한 산술 연산자로는 다음과 같은 것들이 있으며 계산방식은 일반적인 수학 연산과 거의 동일합니다.
연산자 | 기능 |
+ | 더하기 |
- | 빼기 |
* | 곱하기 |
/ | 나누기 |
% | 나머지 |
static void Main(string[] args)
{
int i = 10;
int j = 20;
int s = i + j; //+ 연산자
WriteLine(s);
}
● 문자열 결합
산술 연산자 중 + 연산자는 다음과 같이 문자열 결합에도 사용할 수 있습니다.
static void Main(string[] args)
{
string s1 = "123";
string s2 = "456";
WriteLine(s1 + s2);
}
문자열은 서로 연산하지 않고 단순히 결합되므로 위의 예제는 "123456"이라는 결과를 표시하게 됩니다.
2. 증가/감소 연산자
연산자 | 기능 |
++ | 피연산자를 1증가시킵니다. |
-- | 피연산자를 1감소시킵니다. |
산술 연산자는 피연산자를 2개(이항 연산자) 이상 필요로 하지만 증가/감소 연산자는 단 하나의 연산자(단항 연산자)만을 필요로 합니다.
증가/감소 연산자가 피연산자의 앞에 오는 경우(전위 연산자) 해당 문장이 평가되기 전에 연산자부터 먼저 실행되지만 피연산자의 뒤에 오는 경우(후위 연산자)는 해당 문장이 평가된 후에 실행됩니다.
static void Main(string[] args)
{
int i = 10;
int j = 20;
WriteLine(++i); //11 출력
WriteLine(j++); //20 출력 -> 실제값 21
}
따라서 같은 연산자를 사용했더라도 연산자의 위치에 따라 값이 달라질 수 있으므로 주의가 필요합니다.
3. 관계 연산자
관계 연산자는 두 피연산자 사이의 관계를 나타냅니다.
연산자 | 기능 (왼쪽 피연산자 기준) |
< | 작다. |
> | 크다. |
<= | 작거나 같다. |
>= | 크거나 같다. |
== | 같다. |
!= | 같지 않다. |
상기 모든 관계 연산자는 조건에 따라 결과로 bool형식을 반환합니다.
static void Main(string[] args)
{
int i = 10;
int j = 20;
WriteLine(i < j); //i가 j보다 작으므로 true
WriteLine(j < i); //j가 i보다 크므로 false
WriteLine(i != j); //i와 j는 같지 않으므로 true
}
4. 논리 연산자
논리 연산자는 참/거짓을 피연산자로 하여 평가하는 연산자이며 다음과 같은 연산자가 존재합니다.
연산자 | 기능 |
&& | 피연산자가 모두 참인 경우에만 참(논리곱 연산자) |
|| | 피연산자중 하나라도 참인 경우에만 참(논리합 연산자) |
! | 피연산자를 반대로 하여 평가(부정) |
static void Main(string[] args)
{
bool b1 = true;
bool b2 = false;
WriteLine(b1 && b2); //모두 true가 아니므로 false
WriteLine(b1 || b2); //하나가 true이므로 true
WriteLine(!b1); //b1이 true이므로 false
}
5. 조건 연산자
필요한 피연산자가 3개가 되는 연산자라고 해서 '삼항 연산자'라고도 하며 첫 번째 연산자의 참/거짓에 따라 두번째 혹은 세번째 식이 실행되는 연산자입니다.
static void Main(string[] args)
{
bool b = true;
var result = (b ? "b는 true" : "b는 false"); //b는 true 이므로 ? 다음 두번째 피연산자가 실행
WriteLine(result);
}
첫 번째 피연산자 다음 ? 문자로 두 번째 피연산자를, 그 다음 : 문자로 세 번째 피연산자를 지정합니다. 이 후 첫번째 피연산자의 상태값에 따라 true면 ? 다음 두번째 연산자가, false면 : 다음 세번째 피연산자를 실행합니다.
6. null 조건부 연산자
피연산자의 null(아무 값도 가지지 않은 상태) 상태를 확인하고 null이면 null을 아니면 지정한 멤버 값을 가져오는 연산자입니다.
using System;
using static System.Console;
namespace Test
{
class Test
{
public int member;
}
class MyTestApp
{
static void Main(string[] args)
{
Test test = null;
int? member = null;
//null 조건 연산자를 사용하지 않는 경우
if (test == null)
member = null;
else
member = test.member;
//null 조건 연산자를 사용하는 경우
member = test?.member;
//결과
WriteLine(member);
}
}
}
null 조건부 연산자는 또한 배열 같은 컬렉션 객체에서도 적용됩니다.
using System;
using System.Collections;
using static System.Console;
namespace Test
{
class MyTestApp
{
static void Main(string[] args)
{
ArrayList a = null;
a?.Add(100); //a가 null이므로 add() 메서드는 호출불가
WriteLine(a?[0]); //a가 여전히 null이므로 아무런 내용도 출력하지 않음
}
}
}
7. 비트 연산자
비트(bit) 단위의 연산을 수행하는 연산자입니다.
● 시프트 연산자
시프트 연산자는 다음과 같은 2개의 연산자가 있으며 비트를 직접적으로 이동시키는 연산자입니다.
<< | 피연산자의 비트를 지정한 수만큼 왼쪽으로 이동 |
>> | 피연산자의 비트를 지정한 수만큼 오른쪽으로 이동 |
아래 예제는 byte형 변수 b에 1 값을 저장하고 있습니다.
static void Main(string[] args)
{
byte b = 1;
WriteLine(b);
}
그러면 변수 b는 내부적으로 다음과 같은 비트를 유지하게 됩니다.
0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
이 상태에서 변수 b에 비트 연산자를 적용시키게 되면
static void Main(string[] args)
{
byte b = 1;
WriteLine(b << 1);
}
bit를 1만큼 왼쪽으로 밀게 되고 밀려난 자리는 0으로 채워지게 됩니다.(단, 음수의 경우에는 1로 채움)
0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
따라서 예제의 결과는 2를 표시합니다.
● 비트 논리 연산자
각 비트에 대해 논리적 연산을 수행하는 것으로 다음과 같은 연산자가 존재합니다.
& | 피연산자의 비트에 논리곱 연산을 수행합니다. |
| | 피연산자의 비트에 논리합 연산을 수행합니다. |
^ | 피연산자의 비트에 베타적 논리합 연산을 수행합니다. |
~ | 피연산자의 비트를 반전시킵니다. |
이때 각 비트에서 0은 false로 1은 true로 취급되며 논리곱은 피연산자 모두 true여야만 true를, 논리합은 피연산자 중 하나만이라도 true면 true를, 배타적 논리합은 피연산자의 상태가 서로 다 달라야만 true를 반환합니다.
static void Main(string[] args)
{
byte b1 = 1;
byte b2 = 2;
}
위 예제는 byte형 변수 b1에 1 값을 b2에 2 값을 부여하고 있습니다. 이때 각 변수의 비트는 다음과 같을 것입니다.
b1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
b2 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
이 상태에서 비트 연산자를 적용하게 되면
static void Main(string[] args)
{
byte b1 = 1;
byte b2 = 2;
int r = b1 & b2;
WriteLine(r);
}
결과는 아래와 같이 바뀌게 됩니다.
b1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
b2 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
r | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
예제에서 사용된 &는 논리곱 연산자이므로 두 비트가 모두 1이 되어야만 1이 됩니다. 하지만 b1, b2 두 변수의 비트를 순서대로 나열해 보면 동시에 1이 되는 비트가 없으므로 0으로만 비트가 채워지게 되고 결국 값은 0이 됩니다.
● 할당 연산자
변수에 어떠한 값을 할당하는 연산자로서 다음과 같은 연산자를 활용할 수 있습니다.
연산자 | 기능 |
= | 오른쪽 피연산자값을 왼쪽 피연산자에 할당합니다. |
+= | 피연산자에 + 연산을 수행한 후 왼쪽 피연산자에 결과값을 할당합니다. |
-= | 피연산자에 - 연산을 수행한 후 왼쪽 피연산자에 결과값을 할당합니다. |
*= | 피연산자에 * 연산을 수행한 후 왼쪽 피연산자에 결과값을 할당합니다. |
/= | 피연산자에 / 연산을 수행한 후 왼쪽 피연산자에 결과값을 할당합니다. |
%= | 피연산자의 나머지를 왼쪽 피연산자에 할당합니다. |
&= | 피연산자에 논리곱 연산을 수행한 후 왼쪽 피연산자에 결과값을 할당합니다. |
!= | 피연산자에 논리합 연산을 수행한 후 왼쪽 피연산자에 결과값을 할당합니다. |
^= | 피연산자에 베타적 논리합 연산을 수행한 후 왼쪽 피연산자에 결과값을 할당합니다. |
<<= | 피연산자에 왼쪽 시프트 연산을 수행한 후 왼쪽 피연산자에 결과값을 할당합니다. |
>>= | 피연산자에 오른쪽 시프트 연산을 수행한 후 왼쪽 피연산자에 결과값을 할당합니다. |
static void Main(string[] args)
{
int i = 10;
int j = 20;
i += j; //i와 j피연산자의 값을 모두 합한 결과를 다시 i변수에 할당
WriteLine(i); //30출력
}
● null 병합 연산자
물음표 2개를 사용하는 연산자로, 피연산자의 null(아무 값도 가지지 않은 상태) 상태를 확인하고 null이 아니면 왼쪽 피연산자 값을, null이면 오른쪽 피연산자 값을 반환합니다.
static void Main(string[] args)
{
int? i = null;
WriteLine(i ?? 0); //i가 null이므로 0출력
i = 10;
WriteLine(i ?? 0); //i가 null이 아니므로 10출력
}
8. 연산자 우선순위
연산자를 여러 개 겹쳐서 사용하는 경우 연산자의 우선순위에 따라 식이 계산됩니다.
순위 | 연산자 |
1 | 후위 ++, 후위 --, ?., ?[] |
2 | 전위 ++, 전위 -- |
3 | *, /, % |
4 | +, - |
5 | <<, >> |
6 | <, >, <=, >=, is, as |
7 | ==, != |
8 | & |
9 | ^ |
10 | | |
11 | && |
12 | || |
13 | ?? |
14 | ?: |
15 | =, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=, |= |
우선순위가 같은 경우는 왼쪽에 있는 연산자가 우선이 되며 또한 각 연산자마다 우선순위가 정해져 있다 하더라도 괄호(())를 사용해 묶어주면 괄호 안의 연산자가 더 높은 우선순위를 갖게 됩니다.
static void Main(string[] args)
{
int r = 2 * 2 + 4;
WriteLine(r); //* 연산자가 우선이므로 결과는 8
r = 2 * (2 + 4);
WriteLine(r); //괄호가 우선순위가 높으므로 결과는 12
}
'.NET > C#' 카테고리의 다른 글
[C#] 메서드 (0) | 2021.09.27 |
---|---|
[C#] 제어문 (0) | 2021.09.24 |
[C#] 데이터 (2) | 2021.09.23 |
[C#] 시작하기 (0) | 2021.01.13 |
[C#] MySQL(MariaDB) EntityFramework 사용하기 (0) | 2020.06.04 |