개발하는 리프터 꽃게맨입니다.

[C#] 데이터 형식 본문

언어/C#

[C#] 데이터 형식

파워꽃게맨 2024. 4. 29. 13:47

[데이터 형식]

 

C#은 다양한 종류의 데이터 형식을 제공하고,

수와 텍스트, 이미지, 소리를 다룰 수 있는 데이터 형식도 제공합니다.

 

하지만 이번에 다룰 것은 모든 데이터 형식의 근간을 이루는

'기본 데이터 형식', '상수', '열거형' 입니다.

 

[변수]

변수를 코드에서 보자면 값을 대입시켜 변화시킬 수 있는 요소이지만, 메모리 쪽에서 보면 '데이터를 담는 일정 크기의 공간'이라는 의미를 갖기도 합니다.

그러므로 우리가 C# 코드를 작성하면서 변수를 만들 때는 그 이면에 있는 메모리 세계도 함께 생각해야 합니다.

 

우리가 변수를 하나 선업하며, 이것은 컴파일러에게 "이 변수에 빌요한 메모리 공간을 예약해줘."라고 알립니다.

가장 먼저 데이터 형식을 명시하고 그 다음에 변수 이름을 명시합니다.

그리고 문장 종결을 표시하는 세미콜론을 부텽서 해당 문장의 끝을 컴파일러에게 알려줍니다.

 

 

컴파일러는 int 형식을 위해 메모리 공간을 할당하고 이 공간을 a라는 식별자가 사용할 수 있도록 준비합니다.

선언된 변수 a에는 대입 연산자를 통해 데이터를 입력할 수 있습니다.

 

 

[초기화에 대해서]

 

C, C++ 에서는 변수를 선언한 후 아무 데이터도 입력하지 않으면 이 변수에 '쓰레기 데이터'를 넣는다.

그런데, C#에서는 이런 경우 에러를 띄운다.

아주 착한 녀석

 

[값과 참조]

값 형식은 변수가 값을 담는 데이터 형식을 말하고,

참조 형식은 변수가 값 대신 값이 있는 곳의 위치를 담는 데이터 형식을말합니다.

 

c++의 값과 참조랑 비슷하게 이해하면 될 것 같습니다.

 

스택에 대한 부분은 넘어가겠습니다.

 

[힙]

스택의 경우 자신이 담고 있던 데이터를 할당 및 해제를 알아서 하지만

힙의 경우 저장된 데이터를 스스로 제거하는 메커님즘을 갖고 있지 않습니다.

대신 가비지 컬렉터를 가지고 있는데요, 가비지 컬렉터는 프로그램 뒤에 숨어 동작하면서 힙에 더 이상 사용하지 않는 객체가 있으면 그 객체를 쓰레기로 간주하고 수거하는 기능을 합니다.

 

프로그래머가 원한다면 언제까지라도 데이터를 살릴 수 있는 또 다른 메모리 영역이 힙 메모리의 존재 의의입니다.

힙에 데이터가 존재하면 코드가 scope 를 넘거가도 계속해서 데이터를 유지할 수 있습니다.

 

참조 형식의 변수는 힙과 스택을 함께 이용하는데,

힙 영역에는 데이터를 저장하고 스택 영역에는 데이터가 저장된 힙 메모리의 주소를 저장합니다.

 

[기본 데이터 형식]

C#이 제공하는 기본 데이터 형식에는 모두 15가지가 있습니다.

ㅇㅣ들은 크게 숫자 형식, 논리 형식, 문자열 형식, 오브젝트 형식으로 나뉩니다.

 

이 중에서 문자열 형식과 오브젝트 형식만 참조 형식에 해당하며, 나머지는 모두 값 형식입니다.

 

1) 정수 계열

byte = 부호 없는 1바이트 정수

sbyte = 부호 있는 1바이트 정수

short = 부호 있는 2바이트 정수

ushort = 부호 없는 2바이트 정수

int = 부호 있는 4바이트 정수

uint = 부호 없는 4바이트 정수

long = 부호 있는 8바이트 정수

ulong = 부호 없는 8바이트 정수

char = 유니코드 문자, 2바이트

 

2) 2진수 10진수 16진수

 

3) 부동 소수점 

float 4바이트 부동소수점

double 8바이트 부동소수점

 

4) decimal 형식

실수를 다루는 데이터 형 중 하나로, 부동 소수점과는 다른 방식으로 소수를 다루며 정밀도가 훨씬 높다.

decimal 은 16바이트를 사용한다,

 

 

5) 문자 형식과 문자열 형식

char의 경우 문자 하나를

string 도 지원함

 

 

큰 따옴표를 3개 붙여 쓰면 이스케이프 문자의 도움 업싱도 여러 줄로 이어진 문자열 리터럴을 만들 수 있다.

 

 

[논리 형식]

bool 쓰면 된다.

이거 1바이트다.

 

[object 형식]

무엇이든 지칭할 수 있는 데이터 형식

그것이 가능한 이유는 바로 상속 덕분이다.

그렇기에 object가 자식들을 모두 담을 수 있게 되는것

 

기본 데이터 형식뿐 아니라 모든 복합 데이터 형식, 프로그래머가 만드는 데이터 형식 마저도

이 object 형식으로 상속받는다.

즉, 모든 데이터 형식의 조상이라는 의미

 

C++의 auto와 유사합니다.

 

[박싱과 언박싱]

object 형식은 참조 형식이기 떄문에 힙에 데이터를 할당합니다.

int 형식이나 double 형식은 값 형식이기 떄문에 스택에 데이터를 할당하고요.

그런데 우리는 앞에서 값 형식의 데이터를 object 형식 객체에 담았습니다.

이 경우에는 어느 메모리에 데이터가 할당되는 것일까요? 스택? 힙?

 

object 형식은 값 형식의 데이터를 힙에 할당하기 위한 '박싱' 기능을 제공합니다.

object 형식에 값 형식의 데이터를 할당하려는 시도가 이루어지면 object 형식은 박싱을 수행해서 해당 데이터를 힙에 할당합니다.

 

 

만약

object a = 20;

이라는 코드가 있으면

 

리터럴 20을 그대로 힙 메모리 영역에 할당한 다음

object a가 해당 힙 메모리를 참조하도록 합니다.

 

언박싱이란 힙 주소의 값을 꺼내는 행위를 발하며 이는 복사 방식을 사용합니다.

 

 

마치 C 스타일 캐스팅 하듯 언박싱을 할 수 있다.

언박싱을 하면 b가 참조하는 메모리의 값을 복사해서 리턴한다.

 

[캐스팅]

변수를 다른 데이터 형식의 변수에 옮겨 담는 것은 형식 변환이라고 합니다.

앞서 살펴본 박싱과 언박싱도 값 형식과 참조 형식 간의 형식 변환이라고 할 수 있습니다.

 

우리가 살펴볼 형식 변환은 다음 5가지 입니다.

 

- 크기(표현 범위)가 서로 다른 정수 형식 사이의 변환

- 크기(표현 범위)가 서로 다른 부동 소수점 형식 사이의 변환

- 부호 있는 정수 형식과 부호 없는 정수 형식 사이의 변환

- 부동 소수점 형식과 정수 형식 사이의 변환

- 문자열과 숫자 사이의 변환

 

 

1) 크기가 서로 다른 정수 형식 사이의 변환

가장 중요한것은 '용량'의 차이 입니다.

 

int는 4바이트고 sbyte는 1바이트이기에

문제가 발생할 수도 있다는 것이죠.

 

sbyte -> int 는 상관이 없다만 역은 문제가 됩니다.

오버플로가 발생하게 되죠

 

오버플로우를 한다고 해서 경고가 따로 뜨지는 않습니다.

 

 

 

[크기가 서로 다른 부동 소수점 형식 사이의 변환]

float와 double 사이의 형식 변환에서도 정수 형식끼리의 변환에서 일어났던 오버플로가 그대로 일어날까요?

부동 소수점 특성상 오버플로가 존재하지 않기 때문에 그런 일은 없을 것입니다.

하지만 조금 다른 차원의 문제가 일어나는데, 정밀성에 손상을 입는 것이죠.

 

그래서 정밀한 수를 다뤄야 하는 프로그램에서는 float와 double 사이의 형식 변환을 시도할 때 주의해야 합니다.

 

[부호가 있는 정수 형식과 부호 없는 정수 형식 사이의 변환]

 

비트 그대로 옮겨온다.

 

[부동 소수점 형식과 정수 형식 사이의 변환]

소수점 아래는 버리고 소수점 위의 값만 남긴다.

 

 

[문자열을 숫자로, 숫자를 문자열로]

"12345"와 12345 의 변환을 다룹니다.

int->string 으로의 일반적인 형변환은 허용되지 않습니다.

 

 

역도 마찬가지다. 

 

C#은 정수 계열 형식, 부동 소수점 형식 모두에서 Parse() 라는 메소드를 넣어줬습니다.

이 메소드에 숫자로 변환할 문자열을 넘기면 숫자로 변환해줍니다.

 

 

 

C# 은 숫자 데이터 형식을 문자열로 바꾸는 방법도 존재합니다.

object에는 ToString() 메소드가 존재하고 자식 자료형에 오버라이딩 되어있습니다.

 

 

[상수와 열거 형식]

 변수는 그 이름의 뜻처럼, 담고 있는 데이터를 얼마든지 변경할 수 있는 메모리 공간입니다.

 

상수와 열거 형식은 변수와 달리 안에 담긴 데이터를 절대 바꿀 수 없는 메모리 공간입니다.

 

상수 const

 

열거형

혹은

 

 

열거형의 기반자료형은 정수형식반 허용됨

 

[Nullable 형식]

int 형식의 변수를 선언하면 4바이트의 메모리가 할당됩니다.

C#의 컴파일러는 이 메모리 공간에 반드시 어떤 값이든 넣도록 강제합니다.

원하는 대로 해주지 않으면 C# 컴파일러는 실행 파일을 내주지 않습니다.

 

하지만 프로그래밍을 하다 보면 어떤 값도 가지지 않는 변수가 필요할 때가 가끔 있습니다.

0이 아닌 비어있는 변수, 즉 null 상태인 변수 말입니다.

 

이 경우 변수에게 할당된 메모리 공간을 비워둘 수 있도록 Nullable 형식을 사용하면 됩니다.

 

Nullable 형식의 변수를 선언할 때는 다음과 같이 월래의 데이터 형식 이름 뒤에 ?만 붙여주면 됩니다.

 


Nullable 형식을 사용할 수 있는 경우는 값 형식에 한해서입니다.

참조 형식은 사용할 수 없습니다.

 

 

모든 Nullable 형식은 HasValue 와 Value 2 가지 속성을 갖고 있습니다.

HasValue 속성은 해당 변수가 값을 가지고 있는지 또는 그렇지 않은지를 나타내고, -> bool 

Value 속성은 해당 변수에 담겨있는 값을 나타냅니다. -> 값

 

 

[var]

강력한 형식의 언어 (strong typed language) 이는 변수나 상수에 대해 깐깐하게 형식 검사를 하는 방싱이다.

이는 프로그래머의 실수를 줄여주는 장점이 있다.

 

반대로 약한 형식 검사의 경우 컴파일러나 인터프리터가 해당 변수에 담는 데이터를 보고 자동으로 형식을 지정해주는 것을 의미한다.

 

이는 var 키워드이다. (마치 auto 처럼 동작)

 

단, var은 지역 변수로만 사용할 수 있습니다.

클래스 멤버에서는 var을 사용할 수 없습니다.

 

놀라운 사실, C# 에서는 전역 변수를 지원하지 않습니다.

 

 

[object와 var의 차이점]

object 형식은 값을 박싱해서 힙에 넣어놓는다.

그러나 var의 경우 그냥 자기 자신을 특정한 자료형으로 컴파일 타임에 변경한다.

즉, 데이터의 본체가 스택에 올라간다.

 

 

[문자열 가공하기]

 

[문자열 탐색]

IndexOf() -> 문자열 내에서 찾으려고 하는 지정된 문자 또는 문자열의 위치를 찾습니다. (시작부터 찾기)

LastIndexOf() -> 문자열 내에서 찾으려고 하는 지정된 문자 또는 문자열의 위치를 찾습니다. (끝부터 찾기)

StartsWith() -> 현재 문자열이 지정된 문자열로 시작하는지를 평가 (bool)

EndsWith() -> 현재 문자열이 지정된 문자열로 끝나는지를 평가 (bool)

Replace() -> 현재 문자열에서 지정된 문자열이 다른 지정된 문자열로 모두 바뀐 새 문자열을 반환

 

 

[문자열 변형]

ToLower() -> 문장 전체를 소문자로 바꾸 후 새 문자열을 반환

ToUpper() -> 문장 전체를 대문자로 바꾼 후 새 문자열을 반환

Insert() -> 현재 문자열의 지정된 위치에 지정된 문자열이 삽입된 새 문자열을 반환

Remove() -> 현재 자열의 지정된 우이치로부터 지정된 수만큼의 문자가 삭제된 새 문자열을 반환

Trim() -> 현재 문자열의 앞/뒤에 있는 공백을 삭제한 새 문자열을 반환합니다.

TrimStart() -> 현재 문자열의 앞에 있는 공백을 삭제한 새 문자열을 반환

TrimEnd() -> 현재 문자열의 뒤에 있는 공백을 삭제한 새 문자열을 반환

 

 

 

[문자열 분할하기]

Split() -> 지정된 문자를 기준으로 현재 문자열을 분리한 다음 분리한 문자열의 배열을 반환.

 

SubString() -> 현재 문자열의 지정된 위치로부터 지정된 수만큼 문자로 이루어진 새 문자열을 반환

 

 

역시 좋은 언어라 그런지 많은 것이 준비되어 있는 모습이다.

 

 

[문자열 서식 맞추기]

서식이란 문자열이 일정한 틀과 모양을 갖추는 것을 의미한다.

C#은 문자열 서식화에 사용할 수 있는 간편한 방법 2 가지를 제공하고,

첯ㅅ 번째는 string 형식의 Format() 메소드

또 다른 하나는 문자열 보간이다.

 

[Format 메소드]

writeline 함수는 내부적으로 Format 함수를 사용하고 있기 때문에

format 함수 내부 문법은 writeline 함수에 동일하게 적용된다.

 

 

이 들은 조합하면, 다양한 서식화를 구현할 수 있다.

 

 

서식 문자열에는 

D, X, N, F, E 를 넣어서 10진수 16진수 (,)로 끊어 읽는 수 고정 소수점 지수

등을 표현할 수 있고

 

날짜 및 시간 또한 나타낼 수 있으나

이는 필요할  때 검색해서 찾아보도록 한다.

 

 

[문자열 보간]

 

 

 

문자열 보간이 코드의 양도 적고 가독성이 좋기 때문에, C# 6.0 이상이 지원되는 개발환경이라면 문자열 보간을 사용하는 것이 합리적입니다.