홍정모의 따라하며 배우는 C언어[3.5~3.8]
3.5 정수와 실수
C언어에서 부동 소수점 수를 표현할 때에는 +-를 나타내는 부호부와 10의 제곱 꼴로 나타내는 지수부 그리고 소수점 이하의 부분을 나타내는 분수부의 조합으로 표현되요.
float는 일반적으로 32bit의 크기를 가지고 1bit의 부호를 나타내는 부분과 지수를 나타내는 부분 7bit 가수를 나타내는 부분 23bit를 가지고 있는데요. 그에반해 double은 64bit의 크기를 가져 더 정밀한 실수 표현이 가능해요. 하지만 더 많은 정밀성을 가진다고해서 무작정 double을 쓰는 것은 좋지 않아요. 64bit라는 비교적 큰 메모리 공간을 차지하기 때문에 속도가 32bit float에 비해 속도가 느리게 되요.
3.6 정수의 오버플로우
32bit 컴퓨터에서 signed int 형 변수가 가지는 메모리의 크기는 2의32승 4294967295 이 되요. 만약 여기서 앞에 수 보다 더 큰 수를 넣으면 어떻게 될까요? 그러면 '오버플로우'가 발생하여 대입했던 수 그대로 저장이 안되요. 예를들어 4bit크기만 저장 할 수 있는 공간이 있다고 할게요.
1 | 1 | 1 | 1 |
부호가 없을 경우 최대로 저장될 수 있는 수는 15 가 되겠죠? 만약 16이라는 숫자 저장하려면 적어도 5bit의 공간이 필요해요.
1 | 0 | 0 | 0 | 0 |
이렇게요. 하지만 앞서 4bit의 크기만 저장된다고 했죠? 그래서 실제로 저장되면 앞에있는 1부분이 잘려서
0 | 0 | 0 | 0 |
이렇게 되죠.. 이러한 현상을 "오버플로우" 라고해요.
오버플로우를 확인 할 있는 코드를 볼게요.
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<limits.h> //각종 max,lim 값을 사용가능하게함
#include<stdlib.h>
int main() {
unsigned int i = 0b11111111111111111111111111111111;
// ob : 내가 입력하는 값이 2진수다.
unsigned int u_max = UINT_MAX+5;
signed int i_max = INT_MAX;
signed int i_min = INT_MIN;
printf("%u\n", i); //% : 서식 지정자로 자료형에 알맞은 출력을 위해
printf("%u\n", u_max);
printf("%i\n", i_max);
printf("%i\n", i_min);
//%u가 아닌 %d로 할 경우 -1이 출력 (출력 범위가 다르기 때문)
printf("%u\n", sizeof(unsigned int)); //차지하는 메모리 크기를 알려줌
printf("%u\n", sizeof(i)); //4 byte = 32 bit
//%u : unsigned integer formater
char buffer[33];
_itoa(u_max, buffer, 2); //변수가 담고 있는 형태를 2진수로 바꿔줌
printf("decimal : %u\n", u_max);
printf("binary : %s\n", buffer);
//overflow 표현할 수 있는 범위를 넘었을 때 : 값이 짤려서 나타나는 현상
return 0;
}
u_max 라는 변수에 UNIT_MAX+5 즉 저장할 수 있는 가장 큰 수에 5를 더하여 저장하였기 때문에 "오버플로우"가 발생..
때문에 값이 넘어간 부분은 짤리고 남은 부분 '4'만 남아 출력되었어요.
3.7 다양한 정수형들
각 정수 자료형 마다 값의 범위가 다르고 사용되는 형식 지정자도 재각각이에요. 만약 형식 지정자를 각각 다르게 하였을 경우 어떻게 그 출력값이 바뀌는지 아래의 코드를 통해 확인해 볼게요.
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<limits.h>
#include<stdlib.h>
int main() {
char c = 65;
short s = 200;
unsigned int ui = 3000000000;
long l = 65537L;
long long ll = 12345678908642LL;
printf("char = %hhd, %d %c\n", c, c, c);
printf("short = %hhd, %hd, %d\n", s, s, s);
printf("unsigned int = %u, %d\n", ui, ui);
printf("long = %ld, %hd\n", l, l);
printf("long long = %lld, %ld\n",ll,ll);
return 0;
}
결과 첫째 줄에경우 %hhd는 1byte %hd는 2byte 크기의 정수를 표현할 수 있으므로 65가 각각 출력 되었지만 %c는 문자를 출력해 Ascii 코드의 65에 해당하는 문자 'A'를 출력했어요.
결과 두째줄의 경우 short int의 경우 2byte의 크기를 가지는데 %hhd의 경우 1byte의 크기만을 가지므로 200이라는 127보다 큰 수가 들어와 오버플로우가 발생하여 -56 이라는 값이 출력되었어요.
그 밑에 있는 결과 값들도 결국 오버플로우로 인해 원래 대입된 값들이 출력되지 않은거에요. 이렇듯 자료형에 따른 각각에 알맞은 형식 지정자를 사용해야 올바른 결과값이 도출될 수 있어요.
3.8 8진수와 16진수
앞서 우리는 2진수나 10진수에 대해 다뤄봤었는데요. 2진수는 0,1 2가지의 숫자를 이용해 표현하였고 10진수는 0,1,2,3,4,5,6,7,8,9 10가지의 숫자를 통해 수를 표현했어요. 8진수는 0,2,3,4,5,6,7 8가지 16진수는 16가지의 숫자를 이용해 수를 표현하는 거에요. 8진수와 16진수의 이해를 돕는 코드를 볼게요.
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main() {
unsigned int decimal = 4294967295;
unsigned int binary = 0b11111111111111111111111111111111;
unsigned int oct = 037777777777;
unsigned int hex = 0xFFFFFFFF;
printf("%u\n", decimal);
printf("%u\n", binary);
printf("%u\n", oct);
printf("%u\n", hex);
printf("%o %x %O %X", decimal, decimal, decimal, decimal);
return 0;
}
각각의 진수로의 숫자 변환은 구글에 4294967295 in oct, hex 이렇게 치면 편하게 값을 알 수 있어요.
출처: https://www.inflearn.com/course/following-c#curriculum
홍정모의 따라하며 배우는 C언어 - 인프런 | 강의
'따배씨++'의 성원에 힘입어 새롭게 개발된 C 언어로 시작하는 프로그래밍 입문 강의입니다. '따배씨'와 함께 프로그래밍 인생을 업그레이드 해보세요., - 강의 소개 | 인프런...
www.inflearn.com