『Lena's by ☆볶기!!』: Restart !!

Rorolena
1-3 정보의 종류

-/1. C++에서 제공하는 타입/-

정수 타입의 범위실험
-----------------------------------------------------------------------
int main()
{
 // 변수 정의
 short int si;
 unsigned short int usi;
 int i;
 unsigned int ui;
 long int li;
 unsigned long ul;
 
 // 값 대입
 si = 40000;   //ERROR
 usi = 40000;  //OK
 i = 40000;   //OK
 ui = 40000;   //OK
 li = 40000;   //OK
 ul = 40000;   //OK

 si = 70000;   //ERROR
 usi = 70000;  //ERROR
 i = 70000;   //OK
 ui = 70000;   //OK
 li = 70000;   //OK
 ul = 70000;   //OK

 si = 2200000000; //ERROR
 i = 2200000000;  //ERROR
 li = 2200000000; //ERROR
 usi = 2200000000; //ERROR
 ui = 2200000000; //OK
 ul = 2200000000; //OK

 ui = 4300000000; //ERROR
 ul = 4300000000; //ERROR

 // 음수값 대입
 si = -100;   //OK
 usi = -100;   //ERROR
 i = -100;   //OK
 ui = -100;   //ERROR
 li = -100;   //OK
 ul = -100;   //ERROR

 return 0;
}
-----------------------------------------------------------------------
point

1. unsigned long는 int 표기 없이 변수 선언이 가능하다.

2. signed int는 int와 같은 의미다.

3. unsigned이 붇는 변수 타입은 음수 저장이 가능하다

4. unsigned이 붇는 변수는 일반 변수 타입의 정수에 비하여
절반만의 양수를 담는다.

5. 변수의 허용 범위를 넘는 수를 담을경우
수는 잘리나 프로그램 실행 자체에는 문재가 없다.

주석에는 ERROR로 표기 하였지만 실재로는 Warning으로써
실행 자체에는 문재가 없으나 의도적이 아닐경우 실제 프로그램이
실행되어도 엉뚱한 숫자를 인출하여 문재를 일으킴으로 ERROR로 표기하였다.
(의도적이라도 잠재적으로 문재가 발생하는 특이경우가 생길수있다.)

tip

1. 43억 혹은그 이상의 변수를 저장하려면
일단 C++에서 제공하는 정수 타입에는 43 억 이상을 보관할 타입은 없다.
다만 C++ 표준안에는 존재하지 않지만 비주얼 C++에만 존재하는 대용량
정수 타입 _int64 타입이 있으나 비주얼 C++ 에서만 동작하기에 권장할 방법은 아니다.
대신 확실한 방법으로 long int와 같은 기본 타입의 변수를 클래스를 사용하여
여러개 묶어서 천문학적 숫자를 보관할수 있으며
모든 환경에서 돌아갈수있는 이점이 있다.

타입의 크기를 알아보는 방법
-----------------------------------------------------------------------
#include <iostream>
using namespace std;

int main()
{
 cout << "short int : " << sizeof(short int) << " bytes\n";
 cout << "unsigned short int : " << sizeof(unsigned short nt) << " bytes\n";
 cout << "int : " << sizeof(int) << " bytes\n";
 cout << "unsigned int " << sizeof(unsigned int) << " bytes\n";
 cout << "long int : " << sizeof(long int) << " bytes\n";
 cout << "unsigned long int : " << sizeof(unsigned long int) << " bytes\n";

 return 0;
}
-----------------------------------------------------------------------
point

1. sizeof() 는 C++에서 기본적으로 제공하는 연산자중 하나로서
() 안에 타입 이름을 넣어주면 해당 타입의 크기가 나온게 된다.
다른 사용방법으론 변수 이름을 넣어주면 해당 변수의
타입에 대한 크기가 나오게 된다.

2. short int, int, long int는 각각 2바이트, 4바이트, 4바이트의 크기를 갖는다.

tip

1. C++ 표준안을 살펴보면 정수 타입의 크기를 정확하게 명시 하고 있지 않다.
다만 아래와 같은 최소한의 규정을 가지고 있을 뿐이다.

 1. short int의 크기는 적어도 2바이트보다 커야 한다.
 2. int의 크기는 적어도 short int의 크기보다 커야 한다.
 3. long int의 크기는 적어도 4바이트보다 커야 하고 int의 크기보다 커야 한다.

short int나 long int는 비교적 규정이 명확한 반면에 int에 대한 규정은 애매한 부분이 있다.
사실 int는 시스템의 자연스러운 크기를 따르도록 규정 하고있다.
즉 일반적 윈도우즈(32비트) 환경에서는 4바이트,
MS-DOS(16비트) 환경에서는 2바이트의 크기를 갖는다.
또한 C++ 표준안에는 같은 종류의 signed와 unsigned 타입은
동일한 크기를 갖는다는 규정도 포함 하고 있다.

2. signed와 unsigned

16비트가 갖는 상태

short int 경우의 해석

unsigned short int 경우의 해석


1번째
2번째
3번째
...
32767번째
32768번째
32769번째
32770번째
...
65535번째
65536번째


0000000000000000
0000000000000001
0000000000000010

0111111111111110
0111111111111111
1000000000000000
1000000000000001

1111111111111110
1111111111111111


  0
  1
  2

  32766
  32767
-32768
-32767

-2
-1


0
1
2

32766
32767
32768
32769

65534
65535


10, 8, 16진수의 사용
-----------------------------------------------------------------------
#include <iostream>
using namespace std;

int main()
{
 // 각각 10, 8, 16진법을 사용한다.
 int decimal = 41;   // 10진수
 int octal = 041;   // 8진수
 int hexadecimal = 0x41;  // 16진수

 // 출력
 cout << "41   = " << decimal << "\n";
 cout << "041  = " << octal << "\n";
 cout << "0x41 = " << hexadecimal << "\n";
 
 return 0;
}
-----------------------------------------------------------------------
point

1. 10진수 변환 표기는 정수로, 8진수는 벼환 표기는 0정수,
16진수 변환 표기는 0x정수로 표기한다.

실수 타입의 사용
-----------------------------------------------------------------------
int main()
{
 // 실수 타입 변수 정의
 float f;
 double d;
 long double ld;

 // 변수에 실수 값을 대입 - 1
 f = 0.00123f;
 d = 1.23;
 ld = 123.0;
 
 // 변수에 실수 값을 대입 - 2
 f = 1.23E-3f;
 d = 1.23E0;
 ld = 1.23E2;

 return 0;
}
-----------------------------------------------------------------------
point

1. float타입의 변수를 사용 할때에는 사용 뒤편에 f를 표기하여준다.
f가 표기되어 있지 않으면 double 타입에
상응하는 실수 값이라고 판단하기 때문이다.

2. 가수와 지수를 이용한 과학적 표기방법이 가능하다.
1.23E-3 = 1.23 x 10^-3 = 0.00123
1.23E0 = 1.23 x 10^0 = 1.23
1.23E2 = 1.23 x 10^2 = 123.0

tip

1. 실수 타입의 내부 구조
만약 부동 소수점 방식이 아니라 고정 소수점 방식이 있다면 일정 공간은
정수 부분을 나머지 부분은 소수 부분을 저장하는 방식을사용 할것이다.
그러나 부동 소수점 타입은 변주싀 일정공간에는 유효자리를
나머이 공간에 지수를 저장하고 있다.
이와 같이 부동 소수점 방식으로 보다 넓은 범위의 숫자를 보관할 수 있다.
다만 정밀도를 잃어버릴 수있는 담점 있다.
이단 점은 이진수를 사용해서 정확한 실수 표현이 불가한 점과
가수를 저장하는 공간이 고정되어 있다는 점에서 기인한다.

char 타입의 사용
-----------------------------------------------------------------------
#include <iostream>
using namespace std;

int main()
{
 // char 타입의 변수를 정의
 char a;
 char b;
 char c;

 // 문자를 대입
 a = 'G';
 b = 'O';
 c = 'D';

 // 화면에 출력
 cout << a << b << c << "\n";

 return 0;
}
-----------------------------------------------------------------------
point

1. 문자를 담기 위해선 char타입의 변수를 사용한다.

2. char 타입의 변수의 크기는 1바이트 정도로
256개의 문자중 한 문자를 담을수있다.

tip

1. 문자 타입 변수중 char 타입 외에도 wchar_t가 있다.
char는 표현 할수있는 문자의 수가 제한적인 반면
wchar_t는 세계 각국의 문자와 기호들을 표현 할수있다.
실제 프로그래밍시 char를 주로 사용하고
특별 요구 상황시 wchar_t 타입을 사용한다.

2. wchar_t 타입을 사용하려면
wchar_t a;

a = L'('

와 같이 L을 붙혀 사용해야한다.
(L을 붙이면 wchar_t 타입에 상응한다는 의미가 된다.)

아스키 코드 값 확인
-----------------------------------------------------------------------
#include <iostream>
using namespace std;

int main()
{
 // 'A' 의 아스키 코드 값 확인
 int a = 'A';
 cout << a << "\n";

 // 65를 문자로 표현하면?
 char b = 65;
 cout << b << "\n";

 return 0;
}
-----------------------------------------------------------------------
point

1. 문자 정보를 입력 시에 반듣이
'A'와 같은 형태로  입력을 하여야한다.
('A' 와같은 형태로 입력을 하지않으면 문자를
변수로 인지, 변수를 가져와 반영하게된다.)

2. 일반 변수타입에 문자를 넣으면 숫자가 출력 되고
문자 변수타입에 숫자를넣으면 문자가 출력된다.

tip

1. signed char와 unsigned char
문자 타입은 'int는 signed int와 같다'와 같은 정수 타입 변수와는 달리
char는 항상 signed char가 되지 않는다.
표준안에서는 signed나 unsigned가 될수 있는데에 어느쪽이든
규정하고 있지않다. 즉, 개발 환경에 따라 달라질 수 있다는 말이 된다.
비쥬얼 스튜디오 닷넷에서는 기본적으로 signed char가 되지만
/J 옵션을 사용하는 경우 unsigned char가 된다.
자세한 사항은 MSDN에서 /J 키워드로 자세히 나와있다.

이스케이프 문자열 사용
-----------------------------------------------------------------------
#include <iostream>
using namespace std;

int main()
{
 // Hello, World!로 고쳐쓰기
 cout << "Hello, Workd";
 
 // 백스페이스로 뒤에 두 글자를 지운다.
 cout << "\b\b";

 // 고쳐서 마무리한다.
 cout << "ld!\n";

 return 0;
}
-----------------------------------------------------------------------
point

1. \b\b 문자로 두글자를 지운후
틀린 부분의 문자를 추가로 출력하여 문장을 완성한다.

tip

1. 문자 출력 주의사항
이스케이프 문장중 \(역슬러쉬)나 "(따옴표)와 같은 문장을 출력 할경우에는
문자앞에 \(역슬러쉬)를 꼭 붙여주어야 한다.

2. 이스케이프 문자열
 특수 문자  아스키 코드 상에서의 표현  C++에서의 표현
 개행 문자  NL(LF)  \h
 수평탭  HT  \t
 수직탭  VT  \v
 백스페이스  BS  \b

 캐리지 리턴

 CR  \r

 폼 필드

 FF  \f
 벨소리  BEL  \a
 역슬래쉬  \  \\
 물음표  ?  \?
 작은 따옴표  '  \'
 큰 따옴표  "  \"
 8진수  ooo  \ooo
 16진수  hhh  \xhhh

bool 타입 사용
-----------------------------------------------------------------------
#include <iostream>
using namespace std;

int main()
{
 // bool 타입의 변수 정의
 bool b1;
 bool b2;

 // 값을 대입한다.
 b1 = true;
 b2 = false;

 // 변수의 값을 출력한다.
 cout << "b1 = " << b1 << "\n";
 cout << "b2 = " << b2 << "\n";

 return 0;
}
-----------------------------------------------------------------------
point

1. 선언한 변수의 값이 true, false가 아닌 1, 0으로
출력되며 인식또한 1, 0으로 된다.
(실제로 보관하는 값은 정수다.)

tip

1. 타입의 표시와 실제적인 의미

 표시한 타입

 컴퓨터가 받아들이는 타입

 char

 "char"

 unsigned char

 "unsigned char"

 signed char

 "signed char"

 bool

 "bool"

 unsigned

 "unsigned int"

 unsigned int

 "unsinged int"

 signed  "int"

 signed int

 "int"

 Int

 "int"

 unsigned short int

 "unsigned shor int"

 unsigned short

 "unsigned shor int"

 unsigned long int

 "unsigned long int"

 unsigned long

 "unsigned long int"

 signed long int

 "long int"

 signed long

 "long int"

 long int

 "long int"

 long

 "long int"

 signed short int

 "shor int"

 signed short

 "shor int"

 short int

 "shor int"

 short

 "shor int"

 wchar_t

 "wchar_t"

 float

 "float"

 double

 "double"

 long double

 "long double"

 void

 "void"


2. 헝가리안 표기법
헝가리안 표기법의 기본은 변수의 이름 앞에 타입의 약자를 적어 넣는 것이다.
예로 무언가의 최대 크기를 담는 변수가 있다고 가정하고
이를 헝가리안 표기법이 아닌 평범히 작성하면 이렇게 정의 할 수 있다.
 int maxSize;

 maxSize = 100;

헝가리안 표기법에서는 숫자(numeric)의 약자인 n을 사용해서 이렇게 정의한다.
 int nMaxSize;

 mMaxSize = 100;

이런 헝가리안 표기법을 이용하는 이유는 자신 이외의 다른 개발자가
이코드들을 읽고 쉽게 구조를 파악하게 하기 위함과 동시에 가독성을 높이기 위함이다.
이는 헝가리안 표기법이 주로 윈도우즈 기반 프로그래밍에서 주로 사용되고 있기 때문이다.
비주얼C++, API은 물론 MFC에서 조차 헝가리안 표기법을 사용 하고있다.

하지만 이런 환경에는 문제가 있다.
헝가리안 표기법을 사용해서 만든 변수의 타입이 만약 바뀌면 변수 이름이 바뀌어야 하고
변수를 사용한 곳을 다 찾아서 바꿔주어야 한다. 관리를 소홀히 하게 되면 실제 타입과
변수 이름에 포함된 타입의 약자기 일치하지 않아서 오히려 가독성을 떨어트릴 수도잇다.

이러한 일로 요즘의 강력한 IDE는 헝가리안 표기법을 필요하지 않게 만든다.
변수 이름에 마우스만 가져다 대면 타입을 비롯한 상세정보가 바로 나타나기 때문이다.

-/2. 형변환/-

기본 타입간의 형변환
-----------------------------------------------------------------------
#include <iostream>
using namespace std;

int main()
{
 // 다양한 타입의 변수를 정의한다.
 int i = 65;
 float f = 66.89f;
 char c = 'C';
 bool b = true;

 // 형변환에 사용할 변수들을 미리 정의해둔다.
 // (이런 경우가 더욱 간결할 때가 있다.)
 int f2i, c2i, b2i;
 float i2f, c2f, b2f;
 char i2c, f2c, b2c;
 bool i2b, f2b, c2b;

 // int를 다른 타입으로
 i2f = i; // int -> float
 i2c = i; // int -> char
 i2b = i; // int -> bool

 // float를 다른 타입으로
 f2i = f; // float -> int
 f2c = f; // float -> char
 f2b = i; // float -> bool

 // char를 다른 타입으로
 c2i = c; // char -> int
 c2f = c; // char -> float
 c2b = c; // char -> bool

 // bool을 다른 타입으로
 b2i = b; // bool -> int
 b2f = b; // bool -> float
 b2c = b; // bool -> char

 // 결과 출력
 cout << "int : " << i << "\n\tto float : " << i2f << "\n\tto char : " << i2c << "\n\tto bool : " << i2b << "\n\n";
 cout << "float : " << f << "\n\tto int : " << f2i << "\n\tto char : " << f2c << "\n\tto bool : " << f2b << "\n\n";
 cout << "char : " << c << "\n\tto int : " << c2i << "\n\tto float : " << c2f << "\n\tto bool : " << c2b << "\n\n";
 cout << "bool : " << b << "\n\tto int : " << b2i << "\n\tto float : " << b2f << "\n\tto char : " << b2c << "\n\n";

 return 0;
}
-----------------------------------------------------------------------
point

1. 실수 타입에서 정수 타입으로 형변환하는 경우에는 실수의
소수점 이하 부분이 잘리게 된다.(반올림 되지않으니 절때 주의)

2. 모든 타입에서 bool 타입으로 형변환하는 경우에는 0이 아닌수는
true 즉, 1로 바뀌며 표기된다. (0은 false의 의미를 갖는다.)

tip

1. 형변환 사용상 주의점
위와같이 다른 타입으로 들어가게 될경우
서로 상응하는 규격 혹은 원래 규격보다 큰경우 에는
변환에 손실이 없지만 그렇지 않은경우는 손실이 있다.

문제가 생기는 형변환
-----------------------------------------------------------------------
#include <iostream>
using namespace std;

int main()
{
 // 정수 타입간의 형변환
 int i = 131071;
 unsigned short i2us = i; // int -> unsigned short
 short i2s = i;    // int -> short

 // 실수 타입간의 형변환
 double d = 12345678901234.56789;
 float d2f = d;    // douvle -> float

 // 실수 타입에서 정수 타입으로 형변환
 float f = 76543.21f;
 short f2s = f;    // float -> short

 // 정수 타입에서 실수 타입으로 형변환
 int big_i = 1234567890;
 float i2f = big_i;   // int -> float

 // 결과 출력
 cout << fixed;
 cout << "int : " << i << "\n\tto unsigned short : " << i2us << "\n\tto short : " << i2s << "\n\n";
 cout << "double : " << d << "\n\tto float : " << d2f << "\n\n";
 cout << "float : " << f << "\n\tto short : " << f2s << "\n\n";
 cout << "int : " << big_i << "\n\tto float : " << i2f << "\n\n";

 return 0;
}
-----------------------------------------------------------------------
point

1. 정수 타입간의 형변환
작은 크기의 정수 타입이 보관하기에는 너무 큰 수를 대입하고 있다.
이런 형변환 경우 아주 이상한 값으로 변질되어 버린다.

2. 실수 타입간의 형변환
float 타입으로 보관하기에는 정밀도가 높은 실수를 대입하고 있다.
현변환 시에 보통 근사 값으로 변환 되지만 근사 값으로의
변환도 불가능한 경우에는 이상한 값으로 변질될 수도 있다.

3. 실수 타입에서 정수 타입으로 형변환
실수에서 정수 타입으로 형변환시 소수점이 짤려 76543이 되어야 하지만
short 타입에게는 너무 큰 수다.

4. 정수 타입에서 실수 타입으로 형변환
기본적으로 실수 타입은 정수 타입보다 큰 수를 보관할 수 있지만,
내부 구조상 정밀도를 잃어버릴 수도 있다.

5. cout << fixed;
cout 객체를 통해서 실수 값을 출력할 때 1.23E-3이 아닌 0.00123처럼 출력하게 만든다.
결과를 정확하게 살펴보기 위해서 고정된 소수점 방식으로 출력할 필요가 있다.

명시적인 형변환
-----------------------------------------------------------------------
#include <iostream>
using namespace std;

int main()
{
 // 다양한 타입의 변수 정의
 int i = 65;
 float f = 66.89f;
 char c = 'C';

// 명시적으로 형변환한다
 cout << "int i = " << i << "\n";
 cout << "(char)i = " << (char)i << "\n";
 cout << "(bool)i = " << (bool)i << "\n\n";

 cout << "float f = " << f << "\n";
 cout << "(int)f = " << (int)f << "\n\n";

 cout << "char c = " << c << "\n";
 cout << "(int)c = " << (int)c << "\n\n";

 return 0;
}
-----------------------------------------------------------------------
point

1. 명시적인 형변환에는 임시 변수가 수반된다.
즉 위와같이 (char)i라고 적어주었을 때, 내부적으로
char 타입의 변수가 하나 임시로 만들어진다.
그다음 i의 값이 이 변수에 대입되면서 형변환을 발생한다.

2. 의도적인 형변환시 명시적인 형변환을 사용하면
이것이 의도적임을 명확히 할 수 있다.

tip

1. C++에서는 (char)i 뿐만 아니라 char(i)처럼 사용할 수 있다.