상세 컨텐츠

본문 제목

[C#] 연산자

.NET/C#

by 클리엘 클리엘 2021. 9. 23. 15:45

본문

728x90

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
}

 

728x90

'.NET > C#' 카테고리의 다른 글

[C#] 메서드  (0) 2021.09.27
[C#] 제어문  (0) 2021.09.24
[C#] 연산자  (0) 2021.09.23
[C#] 데이터  (0) 2021.09.23
[C#] 시작하기  (0) 2021.01.13
[C#] MySQL(MariaDB) EntityFramework 사용하기  (0) 2020.06.04

관련글 더보기

댓글 영역