언어 자료구조 알고리즘/Escort C#

[C#] 2.2 해야 할 일에 관한 문법 사항, 2.2.1 연산자

언제나휴일 2016. 4. 1. 16:43
반응형

 컴퓨터 프로그램에는 관리해야 할 데이터 이외에도 동작해야 할 논리를 표현하는 문법이 필요할 것입니다. C#에서는 프로그램의 논리를 표현하기 위해 연산자와 식, 문 등을 제공하고 있습니다.  다른 언어를 접한 적이 있다면 속독으로 보셔도 되는 부분입니다.

 

2.2.1 연산자

 

 연산자는 연산 기호와 피연산자를 사용하였을 때 수행할 행위와 결과 형식에 대한 약속입니다. 다음은 C#에서 제공되는 연산자들과 간략한 사용 예입니다.

 

+ (단항 연산자)

 

 모든 숫자 형식에 제공이 됩니다. 연산 결과는 단순히 피연산자의 값으로 아무 의미가 없습니다.

 

static void Main(string[] args)

{

    int a = 3;

    Console.WriteLine("a:{0} +a:{1}", a, +a);

}

 

+ (이항 연산자)

 

 숫자 형식 사이에 오면 두 수의 합을 계산합니다.

 

static void Main(string[] args)

{

    int i = 2;

    int j = 3;

    Console.WriteLine("{0}+{1}={2}", i, j, i+j);

}

 

 문자열 사이에 오면 두 개의 문자열의 문자 컬렉션을 합한 문자열을 반환합니다.

 

static void Main(string[] args)

{

    string s1 = "hello";

    string s2 = "yahoo";

    Console.WriteLine("{0}+{1}={2}", s1, s2, s1+s2);

}

 

 대리자 사이에 오면 두 개의 대리자에 위임된 행위를 위임한 대리자를 반환합니다. 이 부분은 9장 대리자와 이벤트에서 자세히 다루겠습니다.

 

delegate void ExamDele();

class Program

{

    static void Main(string[] args)

    {

        ExamDele dele1 = new ExamDele(FunA);

        ExamDele dele2 = new ExamDele(FunB);

        ExamDele dele3 = dele1 + dele2;

        dele3();

    }

    static void FunA()

    {

        Console.WriteLine("FunA ");

    }

    static void FunB()

    {

        Console.WriteLine("FunB ");

    }

}

 

- (단항 연산자)

 

 모든 숫자 형식에 제공이 됩니다. 연산 결과는 단순히 피연산자의 -1을 곱한 값입니다.

 

static void Main(string[] args)

{

    int a = 3;

    Console.WriteLine("a:{0} -a:{1}", a, -a);

}

 

- (이항 연산자)

 

숫자 형식 사이에 오면 두 수의 차를 계산합니다.

 

static void Main(string[] args)

{

    int i = 2;

    int j = 3;

    Console.WriteLine("{0}-{1}={2}", i, j, i-j);

}

 

 열거형 형식 사이에 오면 두 열거형 값의 차를 계산합니다. 열거형은 4장 값 형식에서 자세히 다루겠습니다.

 

enum DemoEnum{    A=3, B=8    }

static void Main(string[] args)

{

    DemoEnum e1 = DemoEnum.A;

    DemoEnum e2 = DemoEnum.B;

    Console.WriteLine("{0} - {1} = {2}", e1, e2, e1 - e2);

}

 

* (단항 연산자)

 

 안전하지 않은 컨텍스트에서만 사용이 가능합니다. 포인터 변수 선언문에 사용하거나 피연산자로 포인터 형식이 오면 간접연산이 수행됩니다. 안전하지 않은 컨텍스트와 포인터에 대한 사항은 MSDN을 참고하세요. 참고로 C#에서 안전하지 않은 코드를 사용하기 위해서는 [프로젝트]=>[속성]=>[빌드 탭]을 선택한 후에 안전하지 않은 코드 허용 체크 박스를 선택하여 빌드해야 합니다.

 

static void Main(string[] args)

{

    unsafe

    {

        int a=3;

        int* p = &a;

        *p = 4;

        Console.WriteLine(a.ToString());

    }

}

 

* (이항 연산자)

 

 숫자 형식 사이에 오면 두 수의 곱을 계산합니다.

 

static void Main(string[] args)

{

    int i = 2;

    int j = 3;

    Console.WriteLine("{0}*{1}={2}", i, j, i * j);

}

 

 

 

 

 

/ (이항 연산자)

 

 숫자 형식 사이에 오면 두 수의 나눗셈을 계산합니다. 두 개의 피연산자가 정수형일 때에는 우항에 0이 오면 DivideZeroException이 발생합니다. 두 개의 피연산자가 정수형일 때에는 내림 법칙에 의해 계산됩니다.

 

 피연산자 중의 하나라도 실수가 오면 연산 결과는 실수가 됩니다. 피연사자 중의 하나라도 실수일 때 우항에 0이 오면 연산 결과는 Infinity가 됩니다. 피연산자 중의 하나라도 실수일 때 좌우항이 모두 0이면 연산 결과는 NaN이 됩니다.

 

static void Main(string[] args)

{

    int i = 3;

    int j = 2;

    int intzero = 0;

    Console.WriteLine("{0}/{1}={2}", i, j, i / j); //결과: 1 ,내림 법칙 적용됨

    //Console.WriteLine("{0}/{1}={2}", i, intzero, i / intzero); DivideZeroException 발생

 

    float floatzero = 0.0f;

    Console.WriteLine("{0}/{1}={2}", i, floatzero, i / floatzero); //결과: Infinity

    Console.WriteLine("{0}/{1}={2}", intzero, floatzero, intzero / floatzero); //결과: Nan

}

▶ 결과

3/2=1

3/0=Infinity

0/0=NaN

 

 

 

 

% (이항 연산자)

 

 숫자 형식 사이에 오면 두 수를 나누었을 때 나머지를 계산합니다.

 

static void Main(string[] args)

{

    Console.WriteLine(3 % 2);

    Console.WriteLine(-4 % 10 );

    Console.WriteLine(6.2 % 10);

    Console.WriteLine(-5.2 % 2.1);

}

▶결과

1

-4

6.2

-1

 

& (단항 연산자)

 

 안전하지 않은 컨텍스트에서만 사용이 가능하며 피연산자의 주소를 계산하여 반환합니다.

 

static void Main(string[] args)

{

    unsafe

    {

        int i=2;

        int* p = &i;

        Console.WriteLine("{0}", *p);

    }

}

 

 

& (이항 연산자)

 

 정수 형식 사이에 오면 비트논리곱을 계산합니다. bool 형식 사이에 오면 논리곱을 계산합니다. 예를 들어 6&3 0110(2진수)&0011(2진수)이므로 피연산자의 같은 자리의 비트가 1인 곳만 1이므로 0010(2진수)가 되어 연산 결과는 2가 됩니다.

 

static void Main(string[] args)

{

    Console.WriteLine("{0}&{1}={2}", 6, 3, 6 & 3);

    Console.WriteLine("{0}&{1}={2}", true, false, true & false);

}

▶결과

6&3=2

True&False=False

 

| (이항 연산자)

 

 정수 형식 사이에 오면 비트논리합을 계산합니다. bool 형식 사이에 오면 논리합을 계산합니다. 예를 들어 6 | 3 0110(2진수) | 0011(2진수)이므로 피연산자 중 어느 하나라도 1인 자리는 1이 되므로 0111(2진수)가 되어 연산  결과는 7이 됩니다.

 

static void Main(string[] args)

{

    Console.WriteLine("{0}|{1}={2}", 6, 3, 6 | 3);

    Console.WriteLine("{0}|{1}={2}", true, false, true | false);

}

▶결과

6|3=7

True|False=True

 

 

 

 

^ (이항 연산자)

 

 정수 형식 사이에 오면 비트 논리 배타합(xor) 연산을 계산합니다. bool 형식 사이에 오면 논리 배타합 연산을 계산합니다. 배타합이란 서로 다를 때 참이고 같을 때 거짓을 말합니다. 예를 들어 6 ^ 3 0110(2진수) ^ 0011(2진수)이므로 피연산자의 같은 자리의 비트가 서로 다르면 1이 되므로 0101(2진수)가 되어 연산 결과는 5입니다.

 

static void Main(string[] args)

{

    Console.WriteLine("{0}^{1}={2}", 6, 3, 6 ^ 3);

    Console.WriteLine("{0}^{1}={2}", true, false, true ^ false);

}

▶결과

6^3=5

True^False=True

 

<< (이항 연산자)

 

 왼쪽 피연산자를 둘째 피연산자(int) 만큼 왼쪽으로 비트 이동합니다. 왼쪽 피연산자의 자료형이 32비트 정수일 때는 오른쪽 피연산자의 하위 5비트만 유효합니다. 64비트 정수일 때는 오른쪽 피연산자의 하위 6비트만 유효합니다. 그리고 비트 이동으로 빈 자리는 0으로 채워집니다.

 

 예를 들어 int형 변수 i의 값이 5일 때 i<<2를 요청하면 2비트 이동하여 연산 결과가 20이 됩니다.

 

 그리고 int형 변수 i의 값이 5일 때 i<<33을 요청하면 33 0100001(2진수)이므로 하위 5비트인 00001(2진수)만큼 비트 이동하여 연산 결과가 a(16진수)가 됩니다.

 

 만약, long형 변수 l의 값이 5일 때 l<<33을 요청하면 0100001(2진수)이므로 하위 6비트인 100001(2진수)만큼 비트 이동하여 연산 결과가 a00000000(16진수)가 됩니다.

 

 그리고 long형 변수 l의 값이 5일 때 l<<65를 요청하면 01000001(2진수)이므로 하위 6비트인 000001(2진수)만큼 비트 이동하여 연산 결과가 a(16진수)가 됩니다.

 

static void Main(string[] args)

{

    int i = 5;

    long l = 5;

    Console.WriteLine("int: {0}<<{1}={2}", i, 2, i << 2);

    Console.WriteLine("int: {0}<<{1}={2:X}", i, 33, i << 33);

    Console.WriteLine("long: {0}<<{1}={2:X}", l, 33, l << 33);

    Console.WriteLine("long: {0}<<{1}={2:X}", l, 65, l << 65);

}

▶결과

int: 5<<2=20

int: 5<<33=a

long: 5<<33=a00000000

long: 5<<65=a

 

>> (이항 연산자)

 

 왼쪽 피연산자가 부호 있는 정수(int, long) 형식이면 빈 자리는 부호 비트로 채워지고 부호 없는 정수(uint, ulong) 형식이면 빈자리는 0으로 채워집니다.

 

static void Main(string[] args)

{

    int i = -5;

    uint u = 5;

    Console.WriteLine("{0}>>{1}={2}", i, 2, i >> 2);

    Console.WriteLine("{0}>>{1}={2}", u, 2, u >> 2);

}

▶결과

-5>>2=-2

5>>2=1

 

~ (단항 연산자)

 

 피연산자를 비트 보수 연산을 합니다. 피연사자는 int, uint, long, ulong 형식이 올 수 있습니다.

 

static void Main(string[] args)

{

    int i = -9;

    uint u = 9;

    Console.WriteLine("~{0:X8} => {1:X8}", i, ~i);

    Console.WriteLine("~{0:X8} => {1:X8}", u, ~u);

}

▶결과

~FFFFFFF7 => 00000008

~00000009 => FFFFFFF6

 

= (이항 연산자)

 

 피연산자는 같은 형식이거나 오른쪽 피연산자를 암시적으로 왼쪽 피연산자 형식으로 변환 가능해야 합니다.

 

static void Main(string[] args)

{

    int i = 3;

    int re = 0;

    re = i;

    Console.WriteLine("re:{0}", re);

}

 

 

 

 

+=, -=, *=, /=,%=,&=,|=,^=,<<=,>>= (이항 연산자)

 

 왼쪽 피연산자와 오른쪽 피연산자를 더하기(빼기, 곱하기,...)연산 결과를 왼쪽 피연산자에 대입합니다.

 

static void Main(string[] args)

{

    int i = 3;

    int re = 0;

    re += i;

    Console.WriteLine("re+={0} 수행 후  re:{1}", i,re);

    re -= i;

    Console.WriteLine("re-={0} 수행 후 re:{1}", i, re);

}

 

++, -- (단항 연산자)

 

 자기 자신을 1 증가시키거나 1 감소시킵니다. 연산자가 앞에 오면 연산 결과는 연산을 수행한 후의 자기 자신입니다. 연산자가 뒤에 오면 연산 결과는 연산을 수행하기 전의 값입니다.

 

static void Main(string[] args)

{

    int i = 3;

    int re;

    Console.WriteLine("현재 i:{0}", i);

    re = ++i;

    Console.WriteLine("++i, 연산결과 {0}, i:{1} ", re,i);

    re = i++;

    Console.WriteLine("++i, 연산결과 {0}, i:{1} ", re, i);

}

 

==,  != (단항 연산자)

 

 두 개의 피연산자가 같은지 다른지를 판별하여 bool 형식 결과 값을 반환합니다. 값 형식과 string 형식이 피연산자로 올 경우에는 값이 같은지를 판별합니다. string 형식을 제외한 참조 형식이 피연산자로 올 경우에는 참조하는 개체가 같은지를 판별합니다.

 

static void Main(string[] args)

{

    int i = 3;

    int j = 3;

    Console.WriteLine("i:{0} j:{1}, == 결과:{2}", i, j, i == j);

    object o1 = 3;

    object o2 = 3;

    Console.WriteLine("o1:{0} o2:{1}, == 결과:{2}", o1, o2, o1 == o2);

}

▶ 결과

i:3 j:3, == 결과:True

o1:3 o2:3, == 결과:False

 

<, <=, >, >= (이항 연산자)

 

 피연산자의 크기를 비교한 결과를 bool 형식 값으로 반환합니다. 모든 숫자 형식과 열거형이 피 연산자로 올 수 있습니다.

 

static void Main(string[] args)

{

    int i = 2;

    int j = 3;

    Console.WriteLine("{0}<{1} => {2}", i, j, i < j);

}

 

 

 

&&, || (이항 연산자)

 

 피연산자로 bool 형식이 올 수 있으며 논리곱과 논리합을 수행합니다. && 연산은 왼쪽 피연산자가 거짓인 때 뒤에 코드를 수행하지 않습니다. || 연산은 왼쪽 피연산자 참이면 뒤에 코드를 수행하지 않습니다.

 

static void Main(string[] args)

{

    bool re = TestA() && TestB();

    Console.WriteLine("TestA() && TestB() 결과:{0}", re);

 

    re = TestB() || TestA();

    Console.WriteLine("TestB() || TestA() 결과:{0}", re);

}

private static bool TestB()

{

    Console.WriteLine("TestB");

    return true;

}

private static bool TestA()

{

    Console.WriteLine("TestA");

    return false;

}

▶ 결과

TestA

TestA()&&TestB() 결과:False

TestB

TestB() || TestA() 결과:True

 

 

 

! (단항 연산자)

 

 bool 형식이 피연산자로 올 수 있으며 부정을 반환합니다.

 

static void Main(string[] args)

{

    bool flag = true;

    Console.WriteLine("!{0}=>{1}", flag, !flag);

}

 

[] (이항 연산자)

 

 배열의 요소에 접근할 때 사용할 수 있습니다. 또한, 요소 개체를 보관하는 컬렉션에서 요소를 접근하는 인덱서로 사용이 됩니다. 인덱서는 5장 캡슐화에서 다루겠습니다. 또한, 단항 연산자로 특성(Attribute)에 사용이 됩니다. 이 책에서는 특성은 다루지 않습니다.

 

static void Main(string[] args)

{

    int[] arr = new int[10];

    for (int i = 0; i < arr.Length; i++)

    {

        arr[i] = i + 1;

    }

    foreach (int i in arr)

    {

        Console.WriteLine(i.ToString());

    }

}

 

 이 외에도 C#에서는 개체를 생성할 때 사용하는 new 연산자를 비롯하여 삼항 조건 연산자인 ?:와 왼쪽 피연산자가 null이 아닐 때 연산 결과로 왼쪽 피연산자를 반환하고 null일 때 오른쪽 피연산자를 반환하는 ??를 비롯하여 멤버에 접근하기 위한 .연산자 등을 제공합니다. 여기에 소개되지 않은 더 많은 연산자는 MSDN을 참고하시기 바랍니다.

반응형

'언어 자료구조 알고리즘 > Escort C#' 카테고리의 다른 글

[C#] 5.1 캡슐화 대상(멤버) - 멤버 필드  (0) 2016.05.02
[C#] 5. 캡슐화  (0) 2016.05.02
[C#] 4. 값(value) 형식  (0) 2016.04.01
[C#] 3.4 string  (0) 2016.04.01
[C#] 3.3 배열  (0) 2016.04.01
[C#] 3.2 Boxing 과 UnBoxing  (0) 2016.04.01
[C#] 3. 형식 개요, 3.1 object  (0) 2016.04.01
[C#] 2.2.2 식과 문  (0) 2016.04.01
[C#] 2. C# 구성 요소, 2.1 데이터에 관한 문법 사항  (1) 2016.04.01
[C#] 1. C# 소개  (0) 2016.04.01