제 11강) 진수(진법) 그리고 형변환 |
오늘은 진수(진법)과 형변환에 대해서 알아보도록 하겠습니다.
먼저 진수란 무엇일까요?
예전에 제가 썼던 글에 있던 그림인데요.
크게 진수는 대표적으로 "2진, 8진, 10진, 16진"이 있습니다.
말 그대로 2진법은 숫자 2개(0, 1)로 표현,
8진법은 숫자 8개(0 ~ 7)로 표현,
10진법은 숫자 10개(0 ~ 9)로 표현,
16진법은 숫자 10개(0 ~ 9)와 알파벳6개(A ~ F)로 표현합니다.
1) 진법 표현 |
숫자들은 각 진법에 따라 다르게 표현이 됩니다.
2) 진법 변환 |
각 진법끼리 변환하는 방법이 존재합니다.
이 부분은 수학이지만 다시한번 되뇌어 봅시다.
↑먼저 10진수를 2진수로 바꾸는 계산방법입니다.
그런데 저렇게만 쓰면 되는게 아니라 10001(2)라고 써야합니다.
↑10진수를 8진수로 바꾸는 법입니다.
그런데 저렇게만 쓰면 되는게 아니라 123(8)이라고 써야합니다.
↑10진수를 16진수로 바꾸는 법입니다.
그런데 저렇게만 쓰면 되는게 아니라 1E3(16)이라고 써야합니다.
대표적으로 10진수를 각 진법별로 바꾸는 법을 알아보았습니다만 다른 진법도 다 비슷비슷함으로 넘어가겠습니다.
3) C언어에서 8진수, 10진수, 16진수 |
지난 7번 강의(입력문과 출력문(printf, scanf, scanf_s))에서 잠깐 보았던 기억이 있습니다.
unsigned int num_8 = 012; // 8진수(0으로 시작)
unsigned int num_10 = 10; // 10진수
unsigned int num_16 = 0xA; // 16진수(0x로 시작)
/* 중략 */
printf("<부호가 없는 진수들(10)> \n");
printf("8진수 : %3o, 10진수 : %3u, 16진수 : %3x \n", num_8, num_10, num_16);
printf("8진수 : %3o, 10진수 : %3u, 16진수 : %3x \n\n", num_10, num_10, num_10);
// 두번째 printf(21번줄)문장은 출력되는 수가 각각의 진수로 표현하지 않았을 지라도
// 출력 형식에 맞게 알아서 출력하여 준다는 것을 보여줍니다.
요런 예제가 있었습니다.
8진수의 경우에는 앞에 "0(숫자)"을 붙여줍니다.
10진수는 평소대로 사용하면 되구요.
16진수는 앞에 "0x(숫자0, 알파벳x)"를 붙여서 사용하면 됩니다.
#include <stdio.h>
int main(void)
{
// 꼭 unsigned로 하지 않아도 됩니다.
int num_8 = 012;
int num_10 = 10;
int num_16 = 0xA;
// 진수표현 1(개별 진법으로 표현한 변수 출력)
printf("8진수 : %3o, 10진수 : %3u, 16진수 : %3X \n", num_8, num_10, num_16);
// 진수표현 2(10진수로 선언한 변수를 각 진법에 맞게 출력)
printf("8진수 : %3o, 10진수 : %3u, 16진수 : %3X \n\n", num_10, num_10, num_10);
return 0;
}
위의 예제와 같이 사용하면 됩니다.
그런데 출력을 하게되면
위와 같이 나오게 됩니다.
과연 어떤점이 문제일까요?
위의 예제를 다음과 같이 바꾸어 출력하여봅시다.
#include <stdio.h>
int main(void)
{
// 꼭 unsigned로 하지 않아도 됩니다.
int num_8 = 012;
int num_10 = 10;
int num_16 = 0xA;
// 진수표현 1(개별 진법으로 표현한 변수 출력)
printf("%3o, %3u, %3X \n", num_8, num_10, num_16);
// 진수표현 2(10진수로 선언한 변수를 각 진법에 맞게 출력)
printf("%3o, %3u, %3X \n\n", num_10, num_10, num_10);
return 0;
}
이제 출력해보면
이렇게 나오게 됩니다.
그럼 어느 것이 10진수고 어느 것이 8진수이고, 어느 것이 16진수인지 알 수 있을까요?
(A 빼고.....)
바로 진수파악이 문제입니다.
그럼 위의 예제에 "한 가지"만 추가하여봅시다.
#include <stdio.h>
int main(void)
{
// 꼭 unsigned로 하지 않아도 됩니다.
int num_8 = 012;
int num_10 = 10;
int num_16 = 0xA;
// 진수표현 1(개별 진법으로 표현한 변수 출력)
printf("%#3o, %#3u, %#3X \n", num_8, num_10, num_16);
// 진수표현 2(10진수로 선언한 변수를 각 진법에 맞게 출력)
printf("%#3o, %#3u, %#3X \n\n", num_10, num_10, num_10);
return 0;
}
각 서식문자에 "#"을 넣어주었습니다.
#을 넣은 상태에서 출력을 하게 되면 8진수 앞에는 0이, 16진수 앞에는 0x(또는 0X)가, 10진수 앞에는 아무것도 붙지 않게됩니다.
4) 형변환(Casting) |
형변환 즉, 캐스팅이라고 불리는 이것은 자료형을 변환하는 것을 의미합니다.
int값을 short로, double값을 float 등등 변환을 시키는 것을 의미하죠.
4-1) 자동형변환(일반) |
자동형변환은 아래의 예제와 같은 변환을 의미합니다.
#include <stdio.h>
int main(void)
{
int num1 = 12.5;
double num2 = 13;
printf("num1 = %d \n", num1);
printf("num2 = %f \n", num2);
return 0;
}
4번줄 에서 12.5를 int값으로 자동으로 형변환이 되어 값이 들어가게 됩니다.
int형은 정수형 자료형이므로 0.5의 값은 무시된채 12만 들어가게 되죠.
(즉, 0.5의 값 손실이 일어납니다.)
5번줄 에서는 13은 double값으로 자동으로 형변환 되어 값이 들어가게 되지만 이 경우에는 정수도 실수이므로 값 손실이 없이 형변환되어 들어가게 됩니다.
이렇게 말이지요.
그러므로 자동형변환은 작은 자료형이 더 큰 자료형으로 자동형변환되는 것은 문제가 없으나 큰 자료형에서 작은 자료형으로 자동형변환이 되는 것은 값손실의 문제가 있습니다.
4-2) 자동형변환(정수의 승격) |
CPU가 좋아하는 자료형이 있습니다.
바로 "int형" 자료형인데요.
CPU가 처리하기에 가장 적절한 크기의 정수형 자료형을 "int"로 정의하기 때문이죠.
그래서 그런지 정수 자료형의 계산은 대부분 int형으로 변환되어 계산을 합니다.
char ch1 = 85;
char ch2 = 12;
char ch3 = ch1 + ch2;
위와 같은 코드가 있다고 합시다.
위의 코드는 총 "4번"의 형변환이 일어나게 됩니다.
char ch1 = 85; // 정수값 85를 char형으로 변환
char ch2 = 12; // 정수값 12를 char형으로 변환
char ch3 = ch1 + ch2;
// ch1과 ch2의 값을 다시 int형으로 변환하여 계산한 후에
// 다시 char형으로 변환하여 ch3에 저장
바로 이렇게 말이지요.
그래서 정수 자료형의 계산은 "int형"이 가장 빠릅니다.
※위의 정수의 승격에 대한 내용은 "C언어 표준 ISO/IEC 9899:TC2의 5.1.2.3 Program execution의 10번 문항"에서 자세히 보실 수 있습니다.
4-3) 명시적 형변환 |
"너는 꼭 이거로 바뀌어야 해!!" 라고 명시적으로 형을 변환하는 것을 의미 합니다.
(강제적 변환)
이 경우에는 괄호안에 자료형을 넣어서 명시적으로 알려줍니다.
double num1 = 3.14;
int num2 = 5;
int result = (int)num1 + num2;
3번 줄에서 double형인 num1을 int형으로 명시적으로 형변환을 시켜버립니다.
그래서 계산할 때 num1은 3.14가 아닌 3이되어 계산에 임하게 됩니다.
명시적 형변환 많이 안쓸것같죠?
엄청 많이 쓰이니 꼭 알아두세요.
다음시간에는 |
오늘은 진수(진법), 형변환에 대해서 알아보았습니다.
다음 시간에는 "조건문(if, switch)"에 대해서 알아보도록 하겠습니다.
'Study > C언어' 카테고리의 다른 글
처음하시는 분들을 위한 C언어 기초강의 시즌2 - 13 [조건문2 - switch문] (0) | 2018.10.17 |
---|---|
처음하시는 분들을 위한 C언어 기초강의 시즌2 - 12 [조건문1 - if문] (0) | 2018.10.17 |
처음하시는 분들을 위한 C언어 기초강의 시즌2 - 07 [입력문과 출력문(printf, scanf, scanf_s)] (0) | 2018.10.17 |
처음하시는 분들을 위한 C언어 기초강의 시즌2 - 08 [변수에 대한 추가적인 이야기] (0) | 2018.10.17 |
처음하시는 분들을 위한 C언어 기초강의 시즌2 - 10 [연산자 이야기] (0) | 2018.10.17 |