C#LAB
C# 1.4 · 1부. 기초

연산자와 형변환

값을 셈하고 견주는 기호들과, 타입을 바꿔 담는 방법입니다.

예상 학습 시간 14분 실행 단추가 있는 예제는 고쳐서 실행해 볼 수 있습니다 난이도 입문
개념 설명

값을 셈하고 견주는 기호들

연산자(operator)는 값을 가지고 무언가를 하라는 기호입니다. 더하고 빼는 것부터 두 값이 같은지 견주는 것까지, 프로그램이 하는 일의 대부분은 연산자로 적힙니다.

연산자는 하는 일에 따라 몇 가지로 나뉩니다.

  • 산술 — 더하기·빼기처럼 셈을 합니다. + - * / %
  • 비교 — 두 값을 견주어 참·거짓을 냅니다. == != > < >= <=
  • 논리 — 참·거짓끼리 묶습니다. && || !
  • 대입 — 값을 담습니다. = += -= *= /=
  • 비트 — 숫자를 이진수 자리로 펼쳐 셈합니다. & | ^ ~ << >>

그리고 타입이 서로 다른 값을 함께 셈하려면 한쪽을 다른 쪽 타입으로 바꿔야 합니다. 이것을 형변환(type conversion)이라고 합니다. C#이 알아서 바꿔 주는 경우도 있고, 우리가 직접 밝혀야 하는 경우도 있습니다.

최소 예제 · 편집 가능

정수끼리 나누면 소수점이 사라집니다

아래 코드는 브라우저 안에서 실제로 실행됩니다. 결과를 먼저 짐작해보고 눌러서 맞는지 확인해보세요.

Program.cs
int a = 7, b = 2;

Console.WriteLine(a / b);           // 몫만 남습니다
Console.WriteLine(a % b);           // 나머지
Console.WriteLine((double)a / b);  // 한쪽을 실수로
출력
3 1 3.5

코드는 고쳐서 실행해 볼 수 있습니다. 처음 누를 때만 실행기를 내려받느라 잠시 걸립니다. 적은 코드는 서버로 나가지 않습니다.

7 / 23.5가 아니라 3인 것이 처음에는 뜻밖일 수 있습니다. 정수끼리 나누면 결과도 정수여야 하므로 소수점 아래가 버려집니다. 소수점까지 필요하면 한쪽을 실수로 바꿔야 하고, 그 방법이 위의 (double) 입니다.

상세 사용법

자주 사용하는 연산자

연산자하는 일예시
+ - * /더하기·빼기·곱하기·나누기10 * 3 → 30
%나눈 나머지10 % 3 → 1
+= -=지금 값에 더하거나 뺀 뒤 다시 담기count += 5;
++ --1 만큼 늘리거나 줄이기count++;
== !=같은지 · 다른지age == 20
&& ||그리고 · 또는age >= 20 && isMember
!참·거짓 뒤집기!isStudent

+ 는 문자열에도 쓰이는데, 이때는 셈이 아니라 이어 붙이기가 됩니다. "3" + "4" 는 7이 아니라 "34" 입니다.

&&|| 는 결과가 정해지면 뒤를 보지 않습니다. false && ... 는 뒤가 무엇이든 거짓이므로 오른쪽을 아예 실행하지 않습니다. 이것을 단축 평가라고 하며, 앞에서 조건을 걸러 뒤가 안전할 때만 실행하게 하는 데 자주 사용됩니다.

비트 연산자

숫자를 이진수로 펼쳐 자리마다 셈하는 연산자도 있습니다. 셈을 하려고 쓰기보다는 켜짐·꺼짐 여러 개를 정수 하나에 담을 때 주로 만나게 됩니다. 권한 목록이나 설정 묶음을 이렇게 다루며, 2부에서 배울 플래그 열거형이 바로 그 방식입니다.

연산자하는 일예시 (6은 110, 3은 011)
&양쪽 자리가 모두 1이면 16 & 3 → 2
|한쪽이라도 1이면 16 | 3 → 7
^두 자리가 서로 다르면 16 ^ 3 → 5
~모든 자리를 뒤집기~6 → -7
<< >>자리를 왼쪽·오른쪽으로 밀기1 << 3 → 8

&&& 는 글자가 비슷하지만 하는 일이 다릅니다. && 는 참·거짓을 묶고 앞에서 판가름 나면 뒤를 보지 않지만, & 는 자리마다 셈하며 양쪽을 모두 봅니다. 참·거짓을 다룰 때는 &&|| 를 사용하세요.

타입을 바꾸는 두 가지 길

담을 형식의 범위가 넉넉하면 C#이 알아서 바꿔 줍니다(암시적 변환). intdouble 에 담는 것처럼 값이 잘려 나갈 일이 없는 방향입니다. 반대로 범위가 좁은 형식에 담을 때는 잃는 것이 생기므로 직접 밝혀야 합니다.

int n = 10;
double d = n;        // 암시적 — 그냥 담깁니다

double pi = 3.9;
int m = (int)pi;    // 명시적 — (int) 로 밝힙니다

여기서 (int)3.9 의 결과가 4가 아니라 3이라는 점을 눈여겨보세요. 캐스트는 반올림이 아니라 소수점 아래를 버립니다. 반올림하려면 Convert 를 사용합니다.

캐스트 — 버립니다
int a = (int)3.9;
// a 는 3

int b = (int)3.2;
// b 는 3
Convert — 반올림합니다
int a = Convert.ToInt32(3.9);
// a 는 4

int b = Convert.ToInt32(3.2);
// b 는 3

문자열을 숫자로 바꾸기

사람이 입력한 값은 문자열로 들어옵니다. 그것으로 셈을 하려면 숫자로 바꿔야 하는데, 바꿀 수 없는 값이 들어올 수 있다는 점이 중요합니다. Parse 는 그럴 때 예외를 던지며 멈추고, TryParse 는 멈추지 않고 실패했다고 알려 줍니다.

int n = int.Parse("123");        // 123 — "abc" 였다면 예외

if (int.TryParse("abc", out int m)) {
    Console.WriteLine(m);
} else {
    Console.WriteLine("숫자가 아닙니다");  // 이쪽으로 옵니다
}

사람이 넣는 값을 다룰 때는 TryParse 를 사용하세요. 오타 하나로 프로그램이 멈추는 일을 막아 줍니다. 반대로 숫자를 문자열로 바꾸는 것은 언제나 되므로 ToString() 하나로 끝납니다.

버전 배지

이 문법, 몇 버전부터 사용할 수 있나요

1.0
2.0
3.0
5.0
6.0
8.0
9.0
10.0
14.0
  • 1.0산술 · 비교 · 논리 연산자, 캐스트
  • 2.0?? — null 이면 다른 값을 사용하는 연산자
  • 6.0?. — null 이면 건너뛰는 연산자
  • 8.0??= — null 일 때만 담는 대입
C# 1.0+

이 단원의 연산자와 캐스트는 C# 1.0부터 있던 것이라 버전을 가리지 않습니다. 다만 값이 없을 수 있는(null) 자리를 다루는 연산자들은 뒤에 하나씩 더해졌습니다. ?? 는 왼쪽이 null 이면 오른쪽 값을 사용하고, ?. 는 앞이 null 이면 뒤를 실행하지 않고 넘어갑니다. 지금은 이런 것이 있다는 정도만 알아 두고, 자세한 것은 2부에서 클래스와 참조 형식을 배운 뒤에 다시 보면 됩니다.

실습 문제

직접 해보기

1. 초를 분과 초로 나누기 난이도 하

int total = 137; 을 두고, 이것이 몇 분 몇 초인지 계산해 2분 17초 형태로 출력해보세요.

분은 60으로 나눈 , 초는 60으로 나눈 나머지입니다. 정수끼리 나누면 몫만 남는다는 점이 여기서 도움이 됩니다.
int total = 137; int min = total / 60; int sec = total % 60; Console.WriteLine($"{min}분 {sec}초");
2. 입력값이 숫자일 때만 셈하기 난이도 중

string input = "3.5"; 를 두고, 이것을 double 로 바꿀 수 있으면 2를 곱해 출력하고, 바꿀 수 없으면 안내 문구를 출력해보세요. 프로그램이 멈추지 않아야 합니다.

멈추지 않아야 하므로 Parse 가 아니라 double.TryParse 입니다. 바뀐 값은 out 으로 받습니다.
string input = "3.5"; if (double.TryParse(input, out double value)) { Console.WriteLine(value * 2); } else { Console.WriteLine("숫자로 바꿀 수 없습니다"); }
요약
  • 정수끼리 나누면 몫만 남습니다. 소수점이 필요하면 한쪽을 실수로 바꿉니다.
  • % 는 나머지를 냅니다. 몫과 짝으로 자주 쓰입니다.
  • 캐스트 (int) 는 소수점 아래를 버리고, Convert반올림합니다.
  • 사람이 넣는 값은 TryParse 로 받습니다. 실패해도 멈추지 않습니다.

C# 버전별 변경 이력 에서 각 버전이 무엇을 더했는지 볼 수 있습니다.