C++筆記-變數

變數概論

當我們要進行複雜運算時,變數成為很重要的東西,你可以用變數儲存各種資料,讓電腦記住它。

要如何宣告一個變數?格式為 (變數型態) (變數名稱),我們可以一次宣告很多變數: (型態) (名稱),(名稱),(名稱)...;

ex: int a,b,c;

要注意的是,變數的名稱在同作用範圍下不可重複,只能為英數字、底線(_)、開頭不可為數字、且不能是C++裡面已經定義的名稱(ex:int, char, double, long…)

變數型態:

根據型態的不同,儲存所需容量也會不同,依照平台而有所差異,如果想知道該型態佔了多少空間,可以使用 sizeof(), 以下所提的空間都是在多數 32 位元機器上佔有空間

一、整數 integer

每種整數資料型態都會有一定的值域,若超過的話會發生溢位,使得答案出錯 而 signed/unsigned 表示型態含不含符號,而負數前面都會有一個 “-” ,因此當型態為 unsigned 時,是將所有負值的空間加到正值,讓正值值域更大

型態空間範圍描述
short/short int2 Bytes-2^15~2^15-1短整數
unsigned short/unsigned short int2 Bytes0~2^16-1無符號短整數
int/long int/signed/signed long int/long4 Bytes-2^31~2^31-1整數
unsigned int/unsigned long int/unsigned4 Bytes0~2^32-1無符號整數
long long/long long int8 Bytes-2^63~2^63-1長整數
unsigned long long/unsigned long long int8 Bytes0~2^64-1無符號長整數

二、浮點數 float

就是有小數點的變數

型態空間範圍描述
float4 Bytes-3.4E38~3.4E38單精度浮點數
double/long double8 Bytes-1.7E308~1.7E308倍精度浮點數

建議用double為主,因為double在計算上的精準度比float來得高很多。

三、字串與字元 string and character

用來儲存文字的東西

型態空間範圍描述
char1 Bytes0~277字元
string不定每個0~277字串

string 其實可以說是字元的組合,也就是很多個字元,之後會在講陣列/字串操作時提到。

四、布林值 boolean

用來判斷條件的變數

型態空間範圍描述
bool1 Bytes0/1、true/false布林值

它只能存true(真)或者false(假),通常用於判斷條件的成立


作用範圍 Scope

我們可以將變數的作用範圍分為 全域性變數區域性變數靜態變數常數

定義:

  • 全域性變數:在程式任何地方都可以調用
  • 區域性變數:在特定的記憶體範圍中可以調用
  • 靜態變數:宣告之後可作為全域性變數使用
  • 常數:宣告之後不可再更動其值

看看這個程式碼:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#include<iostream>
using namespace std;
const int s=0; //s是常數,如果在程式的某個地方修改它的值,會報錯
int a; // a是全域變數,可以在f函式也可以在main裡使用
int f(){
	return 1;
}
int main(){
	static int b; //b是靜態變數,可以拿到main函式以外的地方使用
	int c;// c是區域變數,只能在main裡用
	return 0;
}

我們程式是由上往下讀的,因此如果在上面程式碼中的 f 函式、main 函式中間再加一個變數 m,則這個變數只能在 m 下面的程式中也就是 main 函式中調用。


溢值 Value Overflow

試試這支有 bug 的乘法程式,看看它有沒有符合想要的結果:

1
2
3
4
5
6
7
8
9
#include<iostream>
using namespace std;
int main(){
    int a = 100000;
    int b = 400000;
    int mul = a*b;
    cout << mul;//輸出 40000000000
    return 0;
}

這是因為 int 只能儲存 $-2147483647\sim2147483647$ 範圍的值,如果超出範圍,會造成不可預期的結果。

參考:C++筆記-未定義行為

強制轉換類型

C++具有任意強制轉換變數型態的方法,分成隱式轉換跟強制轉換,兩者差別在前者是由編譯器自動轉換,後者由程式設計師強制轉型

1
2
3
int a = 7;
double b = 1.2;
int c = a*b;

在這支程式中,編譯器會先把整數a轉成浮點數(小轉大),計算完後,把結果轉成整數(大轉小)直接去掉小數點後的值再賦值給 c ,最後 c 會是 8,這就是隱式轉換。

1
2
3
int a = 7;
double b = 1.2;
cout << a*(int)b;

這次在 b 前面加了(int),是將 b 先轉成整數再進行運算輸出,此為強制轉換。

除法運算

考慮以下程式片段

1
2
3
4
int a = 3;
int b = 10;
double c = a/b;
cout << a/b << ' ' << c;

將得到輸出為 0 0,在C/C++對int除法時,需特別注意結果只會是商數 $0$ 而不會出現 $0.3$, 直接去掉小數點,此為截斷取整,或稱向零取整。

而在一些其他語言(例如Python)的整數除法是向下取整,即 -10 / 3 在數學上結果是-3.333…,在C++中會得到 -3,若是向下取整會得到 -4

此部分常是程式設計上一大陷阱,若遇到除法、模運算(取餘)應注意是否需先轉換成浮點數型態。