型態轉型

(資料的)

Arvin Liu @ C-Sprout 2021

基本型態

C++的所有基本型態

(Fundamental types)

整數類

Integers

字元類

Characters

小數點類

Floating Point

異類

short

int

long

long long

 

unsigned short

unsigned (int)

unsigned long

unsigned long long

char

unsigned char

char16_t

char32_t

wchar_t

float

double

long double

bool

void

nullptr_t

紅色: 基礎預設型態,例如

  • 1.23預設就是double。
  • 1 預設就是int。

橘色: 你比較用的到的型態。

(一點補充) 科普沒有用不會講到的東西

型態 解釋 所占空間
unsigned char 沒什麼東西,就是可以存0~255的型態。 1 byte,同char。
char16_t 為了存UTF-16 (unicode-16編碼)的型態。 2 bytes。
char32_t 為了存UTF-32 (unicode-32編碼)的型態。 4bytes。
wchar_t 在char16/32_t出現以前,存非常規的字的型態。 通常4bytes,
但windows是2bytes。
long double 比double更大的浮點數型態。不常用且可能不支援。 通常12bytes。
long /
unsigned long
一個與作業系統操作息息相關的整數。大小如右邊所述。(long與指標的大小是相同的) 32位元系統為4bytes,
64位元系統為8bytes。
void 虛空(?) 不可以直接用void當型態,只能用他的指標型態宣告。常用在做各種指標的強制轉換。 1 byte。
nullptr_t 特別的存在,指nullptr的型態。(因nullptr不是實物,所以nullptr的指標 (nullptr_t) 不算在"實物"指標的型態。) 32位元系統為4bytes,
64位元系統為8bytes。
(也就是同指標大小)

跟指標有關的東西可以等第二期資芽的指標課程~

查詢型態大小

沒看過這個型態也???

int ************* a;

sizeof(一個型態/東西)

#include <iostream>
using namespace std;
int main(){
    cout << sizeof(int) << endl;
    cout << sizeof(long long) << endl;
    cout << sizeof(FILE) << endl;
    cout << sizeof(string) << endl;
    cout << sizeof(int *************) << endl;
    
    return 0;
}
4
8
32
24
4 // 64-bit系統會是8

(在32-bit環境下執行的結果)

sizeof(一個型態/東西) = 這個型態/東西佔了多少bytes。

ㄨㄚˊ? 甚麼是bytes?

Special Thanks: Peipei @ sprout week 1

未來你可以自己做一個型態(?)

可以sizeof去衡量你的型態大小!

struct / class

布林值

Boolean

就是true 或 false

沒有true或false的疊加態

Boolean

#include <iostream>
int main(){
    bool t = true;  // 1
    bool f = false; // 0
    bool huh = (5 % 2 == 0);
    if(huh){
    	std::cout << "huh?";
    }else{
    	std::cout << "huh!";
    }
}
huh!

只存true / false的一個神奇型態。

整數類

Integers

整數類

型態 所佔空間 數值範圍 程式表示
(
要#include <climits>)
short (int) 2 bytes SHRT_MIN SHRT_MAX
unsigned short (int) 2 bytes USHRT_MAX
int 4 bytes INT_MIN INT_MAX
unsigned (int) 4 bytes UINT_MAX
long long (int) 8 bytes LLONG_MIN LLONG_MAX
unsigned long long (int) 8 bytes ULLONG_MAX

可以用           
來估算出題目數字會不會超出型態範圍

2^{10} \simeq 10^3

小數點類

Floating Point

浮點數需要知道的兩種型態

 

型態 所佔空間 程式表示
(
要#include <cfloat>)
float 4 bytes FLT_MIN FLT_MAX
double 8 bytes DBL_MIN DBL_MAX

 

不要用 float 用 double!!!!!!!!

非數字的數字

 

奇怪的東西 意思 出現時機
Nan

他不是一個數字可以表達的。

(Not a number)
* Nan != Nan

sqrt(-1)
Inf (Infinity) 1.0 / 0
Ind

沒有被定義。

(Indeterminate)
-1.#IND等同於Nan

inf / inf

 

特殊的表達方式 - e

#include <iostream>
int main(){
    double a = 1;
    double b = 0.5;
    double c = 1.27E1;
    double d = 1.27e1;
    double e = (int)1e5;
    double f = 1.234e-2;
	
    /* cout ommitted*/
    return 0;
}
1
0.5
12.7
12.7
100000
0.01234

小數點可以用 <a>e<b>表示科學記號,
也就是

a \times 10^b

浮點數誤差問題

0.1 + 0.2 = 0.3
#include <iostream>
#include <cmath>
int main(){
    if(0.1 + 0.2 == 0.3)
        std::cout << "IQ180";
    else
        std::cout << "IQ3";
}

嗎?

IQ3
#include <iostream>
#include <cmath>
#define EPS 1e-7
int main(){
    double A = 0.1 + 0.2;
    double B = 0.3;
    if(abs(A - B) < EPS)
        std::cout << "IQ180";
    else
        std::cout << "IQ3";
}
IQ180

EPS (浮點數相對精度)

讓 = 的條件更寬鬆一點,只要在EPS內就當作一樣。

(EPS, epsilon, 一個很小的數字。)

轉型

不是這種轉型

所以我的帽子呢?

各種轉型

  •  顯性轉型 / 強迫轉型

    • 直接告訴程式要轉甚麼東西。
    • 可以在前面加小括號轉型
  •  隱性轉型

    • 讓程式自己處理,hehe。
    • 通常出現在運算式裡面。

異形運算

不同型態的變數的運算 - 隱式轉型

Implicit Casting / Conversion

#include<iostream>
int main()
{
    int x = 10;    // integer x
    char y = 'a';  // character c
  
    // y 被隱式轉換成int
    x = x + y;
     
    // x 被隱式轉換成double
    double z = x + 1.0;
  
    return 0;
}

隱式轉型

隱轉 - 兩邊形態不一樣但是卻可以運算。

隱式轉換鏈

bool < char < int < unsigned < long long < float < double 

整數 < 浮點數,少bit < 多bit,有號(+-) < 無號

兩個型態的運算,看誰比較小就會被轉換。

強制轉型

強迫某個數字轉換型態

強制轉型

總之就前面加小括號就好了。

7.2 (double型態) 強制轉換成 int型態。

cout << (int)7.2
// 7

Special Thanks: 竹區講師日月卦長

型態轉換問題表

型態轉換 舉例 可能的問題
大浮點數 -> 小浮點數 double -> float 損失精準度。(超出未定義)
浮點數 -> 整數 float ->  int 損失小數部分。(超出未定義)
大整數 -> 小整數 long -> int 只複製較低位元組的內容。
符號系列 <-> 沒有符號系列 int <-> unsigned 同大小直接overflow。
#include <iostream>
int main(){
    float a = 123.4567890123456789;
    int b = a;
    int c = 1234567890123456789LL;
    unsigned d = -1;
    /* cout ommitted */
    return 0;
}
123.457
123
2112454933
4294967295

小心隱式規則!!!!

#include <iostream>
int main(){
    double x = 1 / 2;
    double y = 1.0 / 2;
    std::cout << x << std::endl;
    std::cout << y << std::endl;
    return 0;
}

為甚麼x是0,y卻是0.5呢?

小心0.999被砍掉!

#include <iostream>
#include <iomanip>
#include <cmath>
int main(){
    double x = log(243) / log(3);
    std::cout << x << std::endl;
    std::cout << std::fixed << \
    	std::setprecision(16) << x << std::endl;
    std::cout << (int)x << std::endl;
    return 0;
}
5
4.9999999999999991
4

auto - 有必要這麼複雜嗎?

設型態好麻煩==

auto - 懶人工具

#include <iostream>
int main(){
  auto z;
  // compile error.
  auto a=1.1;
  // double. 浮點數預設 double。
  auto a={1,2,3};
  // initializer list,通常只可以拿來for-each。
}

不知道要放甚麼,那就放auto就好啦

請審慎使用<(_ _)>

Review

Review

  • 看到除法先想要不要用double
  • 非特殊情況,不要用float。
  • 會怕過程數字超範圍就開大一點 (如果空間夠的話)。
  • 如果怕會轉歪全部用強制轉換
    (用小括號+型態直接告訴程式要換甚麼。)

型態確認

auto到自己不知道那是甚麼型態 = =

typeid(東西).name()

#include <iostream>
#include <climits>
#include <cmath>
using namespace std;
int main(){
    cout << sizeof(int) << endl;
    cout << sizeof(long long) << endl;
    cout << sizeof(FILE) << endl;
    cout << sizeof(string) << endl;
    cout << sizeof(int *************) << endl;

    cout << typeid(int).name() << endl;
    cout << typeid(long long).name() << endl;
    cout << typeid(FILE).name() << endl;
    cout << typeid(string).name() << endl;
    cout << typeid(int *************).name() << endl;
    return 0;
}
4
8
216
32
8
i
x
8_IO_FILE
NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
PPPPPPPPPPPPPi
Made with Slides.com