1. Introduction
즐겨 보던 C# 교재에 이 부분에 대한 설명이 충분하지 않아 이런 저런 자료를 찾아보고 여기에 요약 정리해 둡니다. 특별한 내용은 없습니다.
연산자는 영어로 "operator"라고 합니다. 예를 들어, C#에서 +, -, *, / 같은 기호는 arithmetic operators(산술 연산자), &&, ||, !같은 기호는 logical operators(논리 연산자)라고 불립니다.
(여기서, 각 연산자의 종류와 이들 연산자들의 연산 '우선순위(operator precedence)'부터 먼저 학습해야 함.)
C#에서 연산자의 결합성(Associativity)은 동일한 우선순위(operator precedence)를 가진 연산자가 여러 개 있을 때, 연산이 수행되는 방향을 결정하는 중요한 개념입니다.
연산자의 결합 법칙(associativity rule)에는 좌측 결합(left associativity)과 우측 결합(right associativity)이 있습니다. 우측 결합 연산자들 사용할 때에는 다소 주의가 필요합니다. 용어에서 실제 의미를 예측하는 것이 다소 어려운 관계로 비교적 이해하기 쉬운 실제 예를 들어보겠습니다.
우선,
1) 동일한 우선순위를 가진 연산자가 몇 개 필요합니다.
2) 그런 다음 계산 순서를 따집니다.
예를 들자면, C# 부분 코드로 다음과 같은 코드가 있다고 가정합니다. 동일한 연산 우선순위를 나타내는 할당 또는 대입 연산자(=)를 연달아 세 개를 사용하는 예입니다.
int a, b, c;
a = b = c = 5;
할당 또는 대입 연산자는 우측 결합성을 가집니다. 세 개의 할당 연산자 중에서 가장 오른쪽에 있는 연산자부터 먼저 연산한다는 뜻입니다.
할당 순서는 다음과 같습니다.
1) c = 5;
2) b = 5;
3) a = 5;
가장 오른쪽에 있는 것을 가장 먼저 계산(=연산)합니다. 가장 오른쪽부터 연산해야 하는 연산자를 우측 결합성을 가지는 연산자라고 합니다.
다음은 좌측 결합성의 예입니다.
int a, b, c, d, e;
a = b = c = d = 7;
e = a + b + c + d; // 덧셈 연산자는 좌측 결합성을 가지는 연산자입니다.
덧셈 연산자는 좌측 결합성을 가지는 연산자입니다. 왼쪽부터 연산합니다. 따라서 연산 순서는 다음과 같습니다.
1) a + b
2) 14 + c
3) 21 + d
4) e = 28
좌측 결합성을 가지느냐 우측 결합성을 가지느냐 하는 문제는 결국 동일하거나 대등한 연산 우선순위를 가지는 연산자들 사이에서 어느 연산을 먼저 계산해야 하느냐 그 순서를 결정하는 문제입니다.
결합 혹은 결합성이라는 용어에서 예상되는 짐작할 수 있는 의미가 실제와는 조금 다르지 않나 생각합니다.
2. Code
// C# 부분 코드입니다. 좌측 결합 예.
int result = 10 - 5 - 2; // (10 - 5) 먼저 계산 후, 결과에서 -2를 수행
Console.WriteLine(result); // 출력: 3
// C# 부분 코드입니다. 우측 결합 예.
int a, b, c;
a = b = c = 5; // c = 5 먼저 수행, 그 후 b = 5, 마지막으로 a = 5
Console.WriteLine(a); // 출력: 5
Console.WriteLine(b); // 출력: 5
Console.WriteLine(c); // 출력: 5
// C# 부분 코드입니다. 괄호를 사용해서 연산 순서를 명시적으로 결정할 수 있습니다.
int result = 10 - (5 - 2); // 괄호를 사용하여 우선순위 변경
Console.WriteLine(result); // 출력: 7
3. Result
......
4. Notes
■ C# 연산자의 종류
연산자는 영어로 "operator"라고 합니다! 예를 들어, C#에서 +, -, *, / 같은 기호는 arithmetic operators(산술 연산자),
&&, ||, ! 같은 기호는 logical operators(논리 연산자)라고 합니다. 각 연산자들의 영어 이름도 많이 사용됩니다.
이하에서는 C#에서 사용되는 다양한 연산자의 영어 명칭을 간략하게 정리합니다.
1) 산술 연산자 (Arithmetic Operators)
'+' (Addition) → 덧셈
'-' (Subtraction) → 뺄셈
'*' (Multiplication) → 곱셈
'/' (Division) → 나눗셈
'%' (Modulo) → 나머지 연산
2) 할당 연산자 (Assignment Operators) : 할당은 간혹 대입이라고도 합니다.
'=' (Assignment) → 값 할당
'+=' (Addition Assignment) → 덧셈 후 할당
'-=' (Subtraction Assignment) → 뺄셈 후 할당
'*=' (Multiplication Assignment) → 곱셈 후 할당
'/=' (Division Assignment) → 나눗셈 후 할당
'%=' (Modulo Assignment) → 나머지 연산 후 할당
3) 증감 연산자 (Increment & Decrement Operators)
'++' (Increment) → 1 증가
'--' (Decrement) → 1 감소
4) 비교 연산자 (Comparison Operators)
'==' (Equal To) → 같음
'!=' (Not Equal To) → 같지 않음
'>' (Greater Than) → 초과
'<' (Less Than) → 미만
'>=' (Greater Than or Equal To) → 이상
'<=' (Less Than or Equal To) → 이하
5) 논리 연산자 (Logical Operators)
'&&' (Logical AND) → 논리 AND
'||' (Logical OR) → 논리 OR
'!' (Logical NOT) → 논리 NOT
6) 비트 연산자 (Bitwise Operators)
'&' (Bitwise AND) → 비트 AND
'|' (Bitwise OR) → 비트 OR
'^' (Bitwise XOR) → 비트 XOR
'~' (Bitwise Complement) → 비트 반전
'<<' (Left Shift) → 왼쪽 시프트
'>>' (Right Shift) → 오른쪽 시프트
7) 조건 연산자 (Conditional Operators)
'? :' (Ternary Operator) → 삼항 연산자
'??' (Null Coalescing Operator) → 널 병합 연산자
이 외에도 다양한 연산자가 있지만, 위 연산자들이 가장 기본적인 것들입니다.
■ 연산자의 결합성(Associativity)
결합성에 대해서 좀 더 살펴보겠습니다. C#에서 연산자의 결합성(Associativity)은 동일한 우선순위를 가진 연산자가 여러 개 있을 때, 연산이 수행되는 방향을 결정하는 중요한 개념입니다.
1) 좌측 결합(Left Associativity)
좌측 결합을 가지는 연산자는 왼쪽에서 오른쪽으로 연산이 수행됩니다. 즉, 같은 우선순위를 가진 연산자가 여러 개 있을 때, 왼쪽에 있는 연산자가 먼저 계산됩니다. 예를 들어, 산술 연산자(+, -, *, /, %)는 좌측 결합을 가집니다. 대부분의 연산자들은 좌측 결합을 가집니다. 우측 결합이 다소 예외적이므로 우측 결합성에 주의합니다.
// C#
int result = 10 - 5 - 2; // (10 - 5) 먼저 계산 후, 결과에서 -2를 수행
Console.WriteLine(result); // 출력: 3
위 코드에서 '10 - 5 - 2'는 (10 - 5) 먼저 계산된 후, 그 결과에서 '-2'가 수행됩니다.
2) 우측 결합(Right Associativity)
우측 결합을 가지는 연산자는 오른쪽에서 왼쪽으로 연산이 수행됩니다. 즉, 같은 우선순위를 가진 연산자가 여러 개 있을 때, 오른쪽에 있는 연산자가 먼저 계산됩니다. C#에서 대입 연산자(=, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, ??=)는 우측 결합을 가집니다.
// C#
int a, b, c;
a = b = c = 5; // c = 5 먼저 수행, 그 후 b = 5, 마지막으로 a = 5
Console.WriteLine(a); // 출력: 5
Console.WriteLine(b); // 출력: 5
Console.WriteLine(c); // 출력: 5
위 코드에서 'c = 5'가 먼저 수행된 후, 'b = c'가 실행되고, 마지막으로 'a = b'가 실행됩니다.
3) 결합성의 실용적 의미
결합성을 이해하면 연산자의 실행 순서를 명확하게 파악할 수 있으며, 코드의 동작을 예측하는 데 도움이 됩니다. 또한, 연산자의 결합성을 변경하고 싶다면 괄호를 사용하여 연산 순서를 명확히 지정할 수 있습니다.
// C#
int result = 10 - (5 - 2); // 괄호를 사용하여 우선순위 변경
Console.WriteLine(result); // 출력: 7
이처럼 C#에서 연산자의 결합성을 이해하면 보다 정확한 코드 작성이 가능합니다.
■ 지정어 연산자(Keyword Operator) : new, typeof, checked, unchecked의 경우.
C#에서 'new'와 'typeof' 연산자는 우측 결합(Right Associativity)을 가지며, 연산이 오른쪽에서 왼쪽으로 수행됩니다.
1) 'new' 연산자 (객체 생성)
'new' 연산자는 객체를 생성하는 데 사용되며, 우측 결합을 가지므로 오른쪽부터 평가됩니다.
// C#
MyClass obj = new MyClass();
위 코드에서 'new MyClass()'가 먼저 실행되어 객체가 생성된 후, 'obj' 변수에 할당됩니다.
# 우측 결합 예제
// C#
MyClass obj = new MyClass().Method();
위 코드에서 'new MyClass()'가 먼저 실행된 후, '.Method()'가 호출됩니다. 즉, 객체를 먼저 생성한 후 메서드를 실행하는 방식으로 평가됩니다.
2) 'typeof' 연산자 (형식 정보 가져오기)
'typeof' 연산자는 컴파일 타임에 형식 정보를 가져오는 연산자이며, 우측 결합을 가집니다.
// C#
Type t = typeof(int);
위 코드에서 'typeof(int)'가 먼저 평가된 후, 't' 변수에 'System.Type' 객체가 할당됩니다.
# 우측 결합 예제
// C#
Console.WriteLine(typeof(MyClass).Name);
위 코드에서 'typeof(MyClass)'가 먼저 평가된 후, '.Name' 속성이 호출됩니다. 즉, 형식 정보를 먼저 가져온 후 해당 속성을 참조하는 방식으로 실행됩니다.
■ 결합성의 의미
'new'와 'typeof' 연산자는 우측 결합을 가지므로, 오른쪽부터 평가됩니다. 이를 활용하면 객체를 생성한 후 즉시 메서드를 호출하거나, 형식 정보를 가져온 후 속성을 참조하는 코드 작성이 가능합니다.
■ 결합성의 의미 추가 1
C#에서 연산자의 결합성(Associativity)은 동일한 우선순위를 가진 연산자가 여러 개 있을 때, 연산이 수행되는 방향을 결정하는 중요한 개념입니다. 일반적으로 산술 연산자(+, -, *, /, %)는 좌측 결합(Left Associativity)을 가지며, 대입 연산자(=, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, ??=)는 우측 결합(Right Associativity)을 가집니다.
하지만 'new', 'typeof', 'checked', 'unchecked' 같은 연산자의 결합성에 대해서는 혼동이 있을 수 있습니다. 일부 자료에서는 좌측 결합이라고 설명하는 경우도 있지만, 공식적인 C# 언어 사양에서는 우측 결합(Right Associativity)을 가진다고 설명됩니다.
1) 'new' 연산자 (객체 생성)
'new' 연산자는 우측 결합을 가지므로, 오른쪽부터 평가됩니다.
// C#
MyClass obj = new MyClass().Method();
위 코드에서 'new MyClass()'가 먼저 실행된 후, '.Method()'가 호출됩니다. 즉, 객체를 먼저 생성한 후 메서드를 실행하는 방식으로 평가됩니다.
2) 'typeof' 연산자 (형식 정보 가져오기)
'typeof' 연산자도 우측 결합을 가지므로, 오른쪽부터 평가됩니다.
// C#
Console.WriteLine(typeof(MyClass).Name);
위 코드에서 'typeof(MyClass)'가 먼저 평가된 후, '.Name' 속성이 호출됩니다.
3) 'checked' 및 'unchecked' 연산자
이 연산자들은 우측 결합을 가지며, 오른쪽부터 평가됩니다.
// C#
int result = checked(10 + 5);
위 코드에서 '10 + 5'가 먼저 평가된 후, 'checked'가 적용됩니다.
결론 :
'new', 'typeof', 'checked', 'unchecked' 연산자는 우측 결합(Right Associativity)을 가집니다. 일부 교재에서 좌측 결합이라고 설명하는 경우가 있지만, 공식적인 C# 언어 사양에서는 우측 결합으로 정의됩니다.
------------------------------------------------------------
■ 결합성 정리 추가 2 - Microsoft 공식 문서 일부분.
1) 연산자 결합성
연산자의 우선 순위가 같은 경우 연산자의 결합성이 연산이 수행되는 순서를 결정합니다.
‘왼쪽 결합성이 있는’ 연산자는 왼쪽에서 오른쪽으로 계산됩니다. 대입 연산자 및 null 병합 연산자 를 제외하고, 모든 이진 연산자 왼쪽 결합성이 있습니다. 예를 들어, a + b - c 는 (a + b) - c로 계산됩니다.
‘오른쪽 결합성이 있는’ 연산자는 오른쪽에서 왼쪽으로 계산됩니다. 대입 연산자, null 병합 연산자, 람다 및 조건 연산자 ?:는 오른쪽 결합성이 있습니다. 예를 들어, x = y = z 는 x = (y = z)로 계산됩니다.
2) 중요
P?.A0?.A1 형식의 식에서 P가 null이면, A0 또는 A1 둘 다 평가되지 않습니다. 마찬가지로 P?.A0.A1 형식의 식에서 P가 null일 때 A0은 평가되지 않으므로 A0.A1도 평가되지 않습니다. 자세한 내용은 C# 언어 사양을 참조하세요.
3) 괄호를 사용하여 연산자 결합성에 따라 주어진 계산 순서를 변경합니다.
// C#
int a = 13 / 5 / 2;
int b = 13 / (5 / 2);
Console.WriteLine($"a = {a}, b = {b}"); // output: a = 1, b = 6
■ 일부분만 발췌한 것이어서 그런지 별 내용이....... 없군요... ㅡ.ㅡ;
추가로 제공되는 PDF 문서는 일단 패스. 관심있으신 분들은 아래 링크 참고. 하단에 보시면 세부 내용별로 PDF 파일을 제공합니다. 분량이 방대합니다.
■ 참고 : checked, unchecked
C#에서 'checked' 연산자는 정수 연산에서 오버플로(Overflow)를 감지하고 예외를 발생시키는 역할을 합니다. 기본적으로 C#에서는 정수 연산에서 오버플로가 발생해도 오류 없이 값이 잘려서 저장됩니다. 하지만 'checked'를 사용하면 오버플로가 발생할 경우 예외를 던져서(=발생시켜서) 오류를 감지할 수 있습니다.
1) 'checked' 연산자의 역할
오버플로 감지: 정수 연산에서 값이 범위를 초과하면 'System.OverflowException'을 발생시킵니다. 안전한 연산 수행: 중요한 계산에서 값이 예상 범위를 초과하는지 확인할 수 있습니다.
2) 'checked' 연산자 사용 예제
// C#
using System;
class Program
{
static void Main() {
try {
int maxValue = int.MaxValue;
int result = checked(maxValue + 1); // 오버플로 발생
Console.WriteLine(result);
}
catch (OverflowException ex) {
Console.WriteLine("오버플로우가 발생했습니다: " + ex.Message);
}
}
}
# 출력 결과 ::
오버플로우가 발생했습니다: Arithmetic operation resulted in an overflow.
위 코드에서 'int.MaxValue + 1'은 'int'의 범위를 초과하므로 'checked'가 예외를 발생시킵니다.
3) 'checked' 블록 사용
'checked' 키워드는 연산자뿐만 아니라 블록 전체에도 적용할 수 있습니다.
// C#
checked
{
int result = int.MaxValue + 1; // 예외 발생
}
위 코드에서는 'checked' 블록 내부에서 수행되는 모든 연산이 오버플로 검사 대상이 됩니다.
4) 'unchecked' 연산자
반대로 'unchecked'를 사용하면 오버플로 검사를 비활성화할 수 있습니다.
// C#
int result = unchecked(int.MaxValue + 1); // 값이 잘려서 저장됨
Console.WriteLine(result); // 출력: -2147483648
위 코드에서는 'unchecked'를 사용하여 오버플로가 발생해도 예외 없이 값이 잘려서 저장됩니다.
5) 언제 'checked'를 사용할까?
- 중요한 계산에서 값이 초과하는지 확인할 때
- 금융, 과학 계산 등에서 정확한 값이 필요한 경우
- 예상치 못한 오버플로로 인해 프로그램이 오작동하는 것을 방지할 때
참고 : Microsoft 공식 문서
https://learn.microsoft.com/ko-kr/dotnet/csharp/language-reference/statements/checked-and-unchecked
.
.
5. Files
부분 코드들 뿐이라. 패스.
6. Ref.
Microsoft 공식 문서. 방대한 문서의 일부분입니다. 각 링크의 세부 내용으로 들어가면 하단에 추가 PDF 문서를 제공하는 경우가 많으니 참고하세요.
1. https://learn.microsoft.com/ko-kr/dotnet/csharp/
2. https://learn.microsoft.com/ko-kr/dotnet/csharp/language-reference/operators/
3. https://learn.microsoft.com/ko-kr/dotnet/csharp/language-reference/statements/checked-and-unchecked
4. 오세만 외 4인 공저, [ C# 프로그래밍 입문 ] 2017. 생능출판.
Happy Programming!
^.^;
'Programming > C# and .NET' 카테고리의 다른 글
C# REF. Notes - 001 - 16진수 데이터 값을 이진수로 출력하기 (0) | 2025.02.11 |
---|---|
유용한 무료 C# 강좌 - 1 (0) | 2024.09.08 |