본문 바로가기

문과 코린이의, [C#] 기록/C# 이론

[문과 코린이의 IT 기록장] C# - 데이터 보관하기 1 (다양한 데이터의 종류, 변수, 값 형식과 참조 형식, 기본 데이터 형식)

반응형

[문과 코린이의 IT 기록장] C# - 데이터 보관하기 1 

(다양한 데이터의 종류, 변수, 값 형식과 참조 형식, 기본 데이터 형식)


 

 

 1. 다양한 데이터의 종류

- 컴퓨터가 무엇을 하느냐는 소프트웨어가 결정한다. 그리고 그 소프트웨어는 사람이 만든다. 따라서, 소프트웨어가 다뤄야 하는 수많은 데이터는 우리가 책임지고 관리해야 한다.

- C#은 다양한 종류의 데이터 형식(Data Type)을 제공한다.

 

[ 데이터 형식 ]

 

 

 

 

 

 

 

 

 

 * 기본 데이터 형식

 * 복합 데이터 형식 : 구조체, 클래스, 배열 등 (이미지, 소리 등의 데이터는 이 형식을 이용해 나타낼 수 있다.)

 ** 값 형식 

 ** 참조 형식 

 cf) 기본/복합 데이터 형식 모두, 값 형식과 참조 형식을 지닌다.

 


 

 

 2. 변수

- 코드에서는, 값을 대입시켜 변화시킬 수 있는 요소

- 메모리에서는, 데이터를 담는 일정 크기의 공간

 * 일정 크기 : 데이터의 형식에 따라 결정된다.

 

[ 변수의 선언 방법 ]

cf ) 변수를 선언하다 : 컴파일러에게 '이 변수에 필요한 메모리 공간을 예약해줘'라고 이야기하는 뜻

int x ;
// int : 데이터 형식
// x : 식별자 (변수 이름)
// ; : 문장 종결

 

 


 

 

 3. 값 형식과 참조 형식

1) 값 형식 및 참조 형식에 대해서

- 값 형식(Value Type) : 변수가 값을 담는 데이터 형식

 * 스택 메모리 영역과 관련 있음

- 참조 형식(Reference Type) : 변수가 값 대신, 값이 있는 곳의 위치(참조)를 담는 데이터 형식

 * 스택 + 힙 메모리 영역과 관련 있음 

[ 메모리 영역 ]
- 스택 (stack) 메모리 영역
- 힙(Heap) 메모리 영역

 


2) 힙과 참조 형식
- 힙은 저장된 데이터를 스스로 제거하는 메커니즘을 가지고 있지 않다. 

- 따라서, 그것을 제거할 수 있도록 C#에는 CLR의 가비지 컬렉터(Garbage Collector)가 존재한다.
 * 가비지 컬랙터 : 프로그램 뒤에 숨어 동작하면서 힙에 더 이상 사용하지 않는 객체가 있으면, 그 객체를 수거하는 기능을 지닌다.


[ 힙 메모리 영역을 사용하는 이유 ]

- 스텍 메모리 영역은, 코드 블록이 사라지는 시점에 함께 제거된다. 따라서 데이터가 사라지지 않게 하고, 유지하고싶을 때는 스택의 구조에 대한 문제가 발생한다.

- 이에 대한 해결점으로, 언제까지라도 프로그래머가 원한다면 데이터를 살릴 수 있는 또 다른 메모리 영역을 CLR이 제공하는 것이다. 

 

[ 참조형식의 변수 ]

- 참조 형식의 변수는 힙과 스택을 함께 사용한다.

 * 힙 공간 : 데이터를 저장

 * 스택 공간 : 데이터가 저장된 힙 메모리의 주소를 저장

- 즉, 데이터를 직접 저장하는 대신, 실제 데이터가 저장된 메모리의 주소를 참조하기 때문에, 참조 형식이라고 불린다.

ex )
{
   // object는 참조 형식
   object a = 10; 
   object b = 20;
}

 

 

 

 

 

 

 

 

 


 

 

 4. 기본 데이터 형식

- 기본 데이터 형식은 C#에서 총 15개 존재하는데, 이들은 크게 '숫자 형식', ' 논리 형식', '문자열 형식', '오브젝트 형식' 으로 나누어진다.

 * 문자열 형식, 오브젝트 형식 : 참조 형식

 * 숫자 형식, 논리 형식 : 값 형식


 1) 숫자 데이터 형식

- C#의 15개 데이터 형식 중, 12가지 형식이 숫자 데이터 형식으로 제공된다.

 * 12가지 형식이, 정수 계열, 부동 소수 계열, 소수 계열 이렇게 3가지로 다시 나뉨

 

(1) 정수 계열 형식

데이터 형식 설명 크기(byte) 담을 수 있는 값의 범위
byte 부호 없는 정수 1(8bit) 0~225
sbyte signed byte 정수 1(8bit) -128~127
short 정수 2(16bit) -323,768~32,767
ushort unsigned short 부호 없는 정수 2(16bit) 0~65,535
int 정수 4(32bit) -2,147,483,648~2,147,483,647
unit unsigned int 부호 없는 정수 4(32bit) 0~4,294,967,295
long 정수 8(64bit) -922,337,203,685,477,508~922,337,203,685,477,507
ulong unsigned long 부호 없는 정수 8(64bit) 0~18,446,744,073,709,551,615

* 한 학급의 성적 처리 프로그램 만들 경우 : int 형식 정도면 충분함

* 회사에서 활용할 회계 프로그램 만들 경우 : int형식은 아마 모자랄 것. long 형식은 되어야 함.

 

 

ex ) 정수 형식 예제 프로그램

 

 

 

 

 

 

 * 큰 자릿수의 정수 리터럴을 타이핑 할 때, 네 자리마다 자리수 구분자(_)를 이용하면 편리하다.

 

 

 

 

 

 

 


(2) 2진수, 10진수, 16진수 리터럴

- 프로그래머는 코드에서도 10진수를 자주 사용하지만, 경우에 따라서는 2진수와 16진수를 다루기도 한다.

 * 2진수 접두사 : 0b

 * 16진수 접두사 : 0x 

 

ex )

 

 

 

 

 

 

 

 


(3) 데이터가 넘처 흐를 때

- 변수는 데이터를 담는데, 일정 형식의 크기를 넘어선 값을 담으면 넘친다. 이를 오버플로(Overflow)라고 한다.

 

ex )

 

 

 

 

 

 

- 오버플로가 되면, uint가 가질 수 있는 최저값으로 돌아오게 된다.

cf ) byte의 최대값은 255이다. 255를 이진수로 바꾸면, '1111 1111'인데, 여기서 +1을 하게 되면, '1 0000 0000'이 된다. 그러나, byte는 8bit만 보관할 수 있기 때문에, 왼쪽을 버리면, 0이 된다.

 

- 이와 같이 데이터를 저장할 때는, 다루려는 데이터이 범위와 변수의 형식을 적절하게 맞춰주는 것이 필요하다.

 

 


 

2) 부동 소수점 형식

- 부동 소수점이란? : 소수점이 고정되지 않고 움직이면서 수를 표현한다. ( 더 넓은 값을 표현하기 위해 )

- 부동 소수점 형식은, 정수뿐 아니라 유리수를 포함하는 실수 영역의 데이터를 다룬다.

 ex) 3.14, 11,08 등..

 

- 이러한 장점이 있음에도 불구하고, 항상 '부동 소수점 형식'을 사용하는 것은 옳지 않다.

a. 부동 소수점 형식은 소수점을 표현하기 위해 일부 비트를 사용하기 때문에, 같은 크기의 정수 계열 형식과, 같은 크기의 수를 표현할 수 없다.

b. 부동 소수점 형식은 산술 연산과정이 정수 계열 형식보다 복잡해서 느리다.

 

[ 부동 소수점 형식 ]

데이터 형식 설명 크기(byte) 범위
float 단일 정밀도 부동 소수점 형식
(7개의 자릿수만 다룰 수 있음)
4(32bit) -3.402823e38~3.402823e38
double 복수 정밀도 부동 소수점 형식
(15~16개의 자릿수를 다룰 수 있음)
8(64bit) -1.79769313486232e308~1.7976933486232e308

 

ex 1)

 

 

 

 

 

 

- 같은 값인데도, float형식 변수와 double형식 변수가 출력하는 지점이 다르다는 것을 알 수 있다.

 * 이와 같은 문제 때문에, float보다는 double을 사용하는 것이 더 좋음.

 

 

- double형을 사용했음에도, 데이터의 손실이 우려될 경우, decimal 형식을 사용하면 된다.

[ decimal 형식 ]

데이터 형식 설명 크기(byte) 범위
decimal 29자리 데이터를 표현할 수 있는 소수 형식 16(128bit)

 

ex 2 )

 

 

 

 

 

 

 

 


 

3) 문자 형식과, 문자열 형식

(1) char형식

: 정수를 다루는 데이터 형식 출신이지만, 수가 아닌 '가','나,','a','b'와 같은 문자 데이터를 다룬다.

 

 [ char 형식 변수에 데이터를 담는 방법 ]

char a = '가';
char b = 'a';
// 작은 따옴표(') 사용

 

ex )

 

 

 

 

 

 

- 이 예제에서는 char 형식의 변수 5개에 문자를 각각 담아 다시 Console.Write()를 통해 화면에 출력했다.

 

- 이 다섯개의 문자를 한번에 담아서 처리할 수 있는 방법이 있는데 그것을 , string이라고 한다.


 

 

char 형식 vs string 형식

 

 

(2) string 형식 ( = 문자열 )

: string 형식은 정해진 크기나 담을 수 있는 데이터의 범위가 따로 정해져 있지 않다. 변수가 담는 텍스트의 양에 따라 그 크기가 달라지기 때문이다.

 

 [ string 형식 변수에 문자열 데이터를 담는 방법 ]

string a = "안녕하세요?";
string b = "김철수입니다.";
// 큰 따옴표(") 사용

 

ex )

 

 

 

 

 

 


 

4) 논리 형식

- 논리 형식이 다루는 데이터는 참(True), 거짓(False) 딱 두 가지이다.

데이터 형식 설명 크기(byte) 범위
bool 논리 형식 1(8bit) true, false

- 논리형식은 프로그래밍에서 가장 많이 사용되는 데이터 형식 중 하나

 : 어떤 작업이 성공했는가?(true), 실패했는가?(false)

 : 두 비교 데이터가 같은가?(true), 다른가?(false)

 

 

ex )

 

 

 

 

 


 

 

5) object 형식

: object 형식은 어떤 물건(데이터)이든지, 다룰 수 있는 데이터 형식이라고 말할 수 있다.

 * object 형식은 상속의 효과 덕분에, 다른 데이터 형식도 마구잡이로 받아올 수 있는 것. 즉, 부모로부터 데이터와 메소드를 물려받은 자식은 부모와 똑같이 동작할 수 있다.

 

- C#은, object가 모든 데이터 형식(기본데이터, 복합 데이터, 프로그래머가 만드는 데이터 형식 모두)를 다룰 수 있도록 한다. 

 

 

다시 말하자면, object형식이 모든 데이터 형식의 조상이 된 것이다.

 

 

ex )

 

object 형식이 모든 데이터를 다 담는 것을 볼 수 있다.

 

 


 

6) 박싱과 언박싱

- object 형식은 참조형식이기 때문에, 힙에 데이터를 할당한다.
- int형, double형같은 경우는 값 형식이기 때문에, 스택에 데이터를 할당한다.
- 그렇다면, 값 형식의 데이터를 object형식 객체에 담았는데, 이 경우에는 어떤 메모리에 데이터가 할당되는 것일까?


 

- object 형식은 값 형식의 데이터를 힙에 할당하기 위한, '박싱(Boxing)'기능을 제공한다.

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

 

 object a = 20;

// 이 코드에서 20은 아래의 그림처럼 박스에 담겨 힙에 할당되고, a는 그 주소를 참조하고 있다.

박싱


 

 

- 이러한 '박싱(Boxing)'이 일어나는 한편, 힙에 있던 값 형식 데이터를 값 형식 객체에 다시 할당해야 하는 경우가 있다. 이는 '언박싱(Unboxing)'이라고 한다.

object a = 20;
int b = (int)a;

// 이 코드에서 a는, 20이 박싱되어 저장된 힙을, 참조하고 있다.

// b는 a가 참조하고 있는 메모리로부터 값을 복사하려고 하는데, 이와 같이 박싱된 값을 꺼내 값 형식 변수에 저장하는 과정을 언박싱이라고 한다.

언박싱

 

 


ex )

* (데이터형식)은 해당 데이터 형식으로 변환하라는 의미이다.

 

 


 

 

7) 데이터 형식 바꾸기

- 변수를 다른 데이터 형식의 변수에 옮겨 담는 것을, 형식 변환(Type Conversion)이라고 한다.

[ 형식 변환의 5가지 ]
(1) 크기(표현 범위)가 서로 다른 정수 형식 사이의 변환
(2) 크기(표현 범위)가 서로 다른 부동 소수점 형식 사이의 변환
(3) 부호 있는 정수 형식과 부호 없는 정수 형식 사이의 변환
(4) 부동 소수점 형식과 정수 형식 사이의 변환
(5) 문자열과 숫자 사이의 변환


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

- 크기가 서로 다른 정수 형식 사이의 변환에서는 '용량'의 차이 때문에 문제를 겪게 된다.

- 즉, 작은 정수 형식의 변수에 있는 데이터를 큰 정수 형식에 옮기는 것은 문제가 없지만, 그 반대의 경우는 오버플로가 발생한다.

 

ex )

 


(2) 크기가 서로 다른 부동 소수점 형식 사이의 변환

- float와 double 사이에서는 형식 변환에서 오버플로의 문제가 발생하지는 않지만(오버플로가 존재하지 X때문), 부동 소수점 형식의 특성상 정밀성에 대한 문제가 발생한다.

 

ex )


 

(3) 부호 있는 정수 형식과, 부호없는 정수 형식 사이의 변환

ex )


(4) 부동 소수점과 정수 형식 사이이 변환

ex )


(5) 문자열을 숫자로, 숫자를 문자열로

[ 문자열을 숫자로 바꾸기 ]

int a = int.Parse("12345");
float b = float.Prase("123.45");

- C#에서는 문자열을 숫자로 변경하기 위해, 정수 계열 형식, 부동 소수점 형식 모두에게 "Parse()"라는 메소드를 넣어준다.

 

[ 숫자를 문자열로 바꾸기 ] 

int c = 12345;
string d = c.ToString();

float e = 123.45;
string f = e.ToString();

- C#에서는 숫자 데이터 형식을 문자열로 바꾸기 위해, object로부터 물려받아 재정의한 "ToSTring()"라는 메소드를 호출한다.

 

 

ex )

 


* 유의사항
- 아직 공부하고 있는 문과생 코린이가, 정리해서 남겨놓은 정리 및 필기노트입니다.
- 정확하지 않거나, 틀린 점이 있을 수 있으니, 유의해서 봐주시면 감사하겠습니다.
- 혹시 잘못된 점을 발견하셨다면, 댓글로 친절하게 남겨주시면 감사하겠습니다 :)
반응형