본문 바로가기

C & C++

C/C++ 기초 - 자료형 ( Data type )

기억 단위


Bit

 

 Bit(Binary Digit)는 데이터(가공된 정보)의 최소 단위입니다. 2진법(Binary)이기 때문에 0과 1로만 이루어져 있습니다.

 약자는 소문자 b.

 

Byte

 

 Byte는 컴퓨터가 데이터를 처리하는 최소 단위입니다. 1Byte는 8Bit인데, 그 이유가 ASCII 문자를 저장하기에 필요한 비트 수가 7비트였고, 2진법으로 다루기 편한 게 8비트였기 때문이라고 합니다.

 여러 나라의 문자를 표기하기에 1Byte로는 부족하기 때문에 한글 등의 문자를 사용할 때는 2Byte의 공간을 사용합니다.

 약자는 대문자 B.

 

 Byte 이후로 Kilobyte, Megabyte 등등이 있는데, 1 Byte x 2^10 = 1 Kilobyte이고 1 Kilobyte x 2^10 = 1 Megabyte, ... 이와 같은 방식으로 1024(2^10) 배가 될 때마다 단위가 증가합니다.

 

 내용을 정확히 이해하기 위한 선수과목으로 진법, 컴퓨터 구조, 메모리에 대한 이해가 필요합니다.


 

데이터 저장 방식


 위에서 얘기했듯이 컴퓨터는 데이터를 최소 bit의 단위로 저장합니다. bit는 0과 1만 있으므로 2진법이라고 볼 수 있습니다. 위의 그림은 10진수 1,857,514,966을 2진법으로 전환해서 컴퓨터에 저장했을 때의 예시입니다. 16진법으로 표현하면 0x6EB76DD6 입니다.


 

자료형( 데이터 타입, Data Type )

자료형의 크기는 Visual Studio 64bit 환경에서 sizeof()를 사용하여 작성되었습니다.

컴파일러마다 자료형의 크기가 다를 수 있습니다.


정수 타입

 

 정수 타입은 양의 정수, 0, 음의 정수를 표현할 때 사용합니다. 기본적으로 맨 앞에 1bit의 부호비트(0일 때 양수, 1일 때 음수)가 사용됩니다. 그러므로 32bit짜리 정수 자료형은 부호비트를 제외하고 [ -2^31 ~ 2^31 - 1 ]이 숫자의 범위가 됩니다.

 모든 정수 타입은 unsigned를 함께 선언함으로써 부호비트를 사용하지 않을 수 있습니다. 이 경우 32bit짜리 정수 자료형의 숫자 범위는 [ 0 ~ 2^32 - 1 ]이 됩니다.

 

 int( integer )

 int는 4 Byte 정수 자료형입니다. 4 Byte보다 작았던 때도 있지만 현재는 4 Byte로 사용됩니다. 정수 자료형이 필요할 때 대부분 int형을 사용합니다.

 숫자의 범위는 [ -2,147,483,648 ~ 2,147,483,648 ], unsigned [ 0 ~ 4,294,967,295 ] 입니다.

 

 

 short

 short는 2 Byte 정수 자료형입니다.

 숫자의 범위는 [ -32768 ~ 32767 ], unsigned [ 65,536 ] 입니다.

 

 

 long

 long은 4 Byte 정수 자료형입니다. int가 4 Byte가 아닐 때 사용되었지만 int와 크기가 같아져서 현재는 잘 사용하지 않습니다.

 숫자의 범위는 [ -2,147,483,648 ~ 2,147,483,648 ], unsigned [ 0 ~ 4,294,967,295 ] 입니다

 

 long long

 long long은 8 Byte 정수 자료형입니다. int보다 큰 자료형이 필요할 때 사용합니다.

 숫자의 범위는 [ -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 ],

 unsigned [ 0 ~ 18,446,744,073,709,551,615 ] 입니다.


실수 타입

 

 실수 타입도 정수 타입과 마찬가지로 부호비트가 존재합니다. 하지만 unsigned는 실수 자료형과 함께 사용할 수 없습니다. 실수를 2진법으로 표현하는 방식으로 부동 소수점(floating point)를 사용하는데, 부호비트 1bit, 지수부의 8bit, 가수부 23bit를 사용합니다. 4 Byte 실수 타입의 숫자 범위는 [ -3.4e+38 ~ 3.4e+38 ] 입니다. 여기서 e+38은 10의 38 제곱을 뜻합니다. 

 


 부동 소수점

 부동 소수점 계산 방법은 다음과 같습니다.(부동 소수점 계산 방법은 꼭 알지 않아도 되는 부분이니 관심이 없으시다면 넘겨주세요.)

 부동 소수점은 실수를 2진법으로 만든 후 정수 부분이 1이 될 때까지 소수점을 이동시킵니다.

 (ex. 1011.1101 -> 1.0111101)

 이 과정에서 소수점이 왼쪽으로 이동한 만큼 2의 지수가 증가하고 오른쪽으로 이동한 만큼 지수가 감소합니다. 현재 예시에서 왼쪽으로 3번 이동했으므로 2의 지수는 3입니다. 이 숫자들을 부호비트, 지수부, 가수부에 넣으면 이렇게 됩니다.

 

 

 

 이제 설명한 방법으로 4 Byte 실수 타입의 양수 최소 값( 1.1e-38 )과 양수 최대 값( 3.4e+38 )을 구하는 계산을 보여드리겠습니다.

 

 지수부(8bit)의 최대 값은 127입니다. 지수부에서 0000 0000을 -127로 하는 바이어스 표현법을 사용하는 데다가 0000 0000(-127) 은 0, 1111 1111(128)은 inf(infinite)로 사용하기 위해 예약되어 있어서 최대 값이 127이 됩니다. 가수부(23bit)에서 가능한 값(정수 1 포함)은 16,777,215 입니다. 하지만 가수부는 전부 소수 부분이므로 정수로 만들기 위해 소수점을 오른쪽으로 23번 이동시키고 지수에서 23을 뺍니다. 그럼 지수는 104가 되고, 최대 값 16,777,215에 2^104를 공학 계산기에서 곱해주면 3.4e+38의 결과를 얻을 수 있습니다.

 

 

 최소 값은 간단합니다. 지수부의 최소 값은 -126, 가수부의 최소 값은 1입니다. 계산하면 1.17e-38의 결과를 얻을 수 있습니다.

 

 

 양수인지 음수인지는 위와 같은 방식으로 값을 구한 뒤에 부호비트가 0이면 그대로, 1인 경우 -를 붙이게 됩니다. 

 

 

 부동 소수점 최소 값, 최대 값은 MSDN을 참고했습니다.

출처 : MSDN https://docs.microsoft.com/ko-kr/cpp/c-language/type-float?view=msvc-160

 

 그리고 위와 같이 소수를 2진법으로 처리하다 보면 무리수거나 소수점을 옮기는 과정에서 버려지는 값이 생겨서 정확하게 원하는 값이 나오지 않을 수도 있습니다. 실수 연산을 할 때는 이점을 유의하여 근삿값임을 인지해야 합니다.


 

 float( floating point )

 float은 4 Byte 실수 자료형입니다. 단정도(single precision)이라고도 합니다.

 숫자의 범위는 [ 1.17e-38 ~ 3.40e+38 ]입니다.

 

 double( double precision )

 double은 8 Byte 실수 자료형입니다. float에 비해 2배의 바이트인 만큼 float보다 정확도가 비교적 높습니다. 부호비트 1bit와 지수부 11bit, 가수부 52bit로 구성되어 있습니다.

 숫자의 범위는 [ 2.22e-308 ~ 1.79e+308 ] 입니다.

 

 long double

 long double은 8 Byte 실수 자료형입니다. 제 환경 기준으로 8바이트지만 다른 컴파일러 환경이면 더 큰 크기의 Byte를 가질 수도 있습니다. 크기가 커지는만큼 정확도도 높아집니다.

 숫자의 범위는 [ 2.22e-308 ~ 1.79e+308 ] 입니다.

 


논리 타입

 

 bool( boolean )

 참과 거짓만을 구분하기 위해 사용되는 1 Byte 논리 자료형입니다. bool형은 0은 0으로, 0을 제외한 모든 숫자는 1로 받습니다. 여기서 0은 false, 1은 true입니다. bool은 원래 C의 기본 자료형은 아니었지만 C++에서 추가되었고 최근에는 C 컴파일러에도 포함되고 있다고 합니다.

 


문자 타입

 

 char( character )

 char는 문자를 출력하기 위한 1 Byte 문자 자료형입니다. 기본적으로 숫자를 입력받고 ASCII 코드에서 그 숫자에 맞는 문자를 출력합니다. 숫자 입력이 가능하므로 정수 자료형처럼 사용할 수도 있습니다. unsigned도 사용할 수 있습니다.

 숫자의 범위는 [ -128 ~ 127 ], unsigned [ 0 ~ 255 ] 입니다.

 


Void 타입

 

 void

 void는 비어있음을 뜻합니다. 따라서 함수를 호출하거나 작성할 때 자주 생략되기도 합니다. 나중에 포인터를 배운 후 void*를 배우게 되면 사용법이 늘어납니다.


 

Endian


출처 : 위키백과 https://ko.wikipedia.org/wiki/%EC%97%94%EB%94%94%EC%96%B8

 

 Endian은 컴퓨터에서 데이터를 저장할 때 저장되는 순서의 방식에 대한 것입니다. Big-Endian 방식은 16진수 0x12345678을 넣었을 때 메모리 순서대로 12 34 56 78로 저장됩니다.(숫자 사이의 띄어쓰기는 각 2개의 숫자가 1 Byte 임을 의미합니다.) Little-Endian 방식은 78 56 34 12 순으로 저장됩니다. Intel CPU를 사용하는 경우에도 여기에 해당됩니다.

 

 이 밑의 내용은 포인터에 대한 이해가 필요한 내용입니다. 포인터를 알고 계시고 궁금하신 분께서만 봐주시기 바랍니다.

 

 shrot 배열에 112(0x70)와 135(0x87)를 넣었습니다. 이것을 int* 변수에 형 변환시켜서 넣고 값을 보면 8,847,472라는 값이 나옵니다. 제가 Big-Endian 환경이 없으므로 확인할 수 없지만, 아마 Big-Endian 환경에서는 00 70 00 87 순으로 저장되어 int*로 받았을 때, 7,340,167이라는 값이 나왔을 것입니다. 물론 애초에 이런 식의 형 변환이 있어서는 안 되겠지만, Little-Endian 환경에서는 이런 방식이 내가 원하는 대로의 값이 나오지 않을 수 있음 알아두어야 합니다.