2016年5月1日 星期日

給新手的C++教學 (上冊) - A. 補充資料 (Additional materials)

回到「給新手的C++教學 (上冊)」

上一章 (這要怎麼定義上一章啦喂)

本教學以「容易理解」為目標,因此對某些觀念進行了簡化
以下提供更正確、更詳細的資訊供讀者們參考
但還是建議新手們先看懂教學內文的解說
(我們學物理時也是先學錯誤但簡單的牛頓力學,沒有一開始就在教量子力學的對吧?)

(注意:註釋的編號並不代表在教學中出現的順序)

註1:(感謝pr3pony)
int 在標準中只規定至少要 2 bytes
雖然幾乎所有編譯器實作依據的標準都是 ILP32 或 LP64
也就是常見的 4 bytes

註2:(感謝pr3pony)
float 的底數其實是 2 不是 10
因此事實上在儲存 float 前,並沒有「轉成二進位」的這個操作
一切都是直接以「二進位」的模式處理
並沒有牽涉到任何「二進位和十進位互相轉換」的操作 (除非要輸出給我們看)
因此,「24005」應該會被轉換成「$(1.01110111000101)_2*2^{14}$」(二進位版的科學記號)
其中「$(1.01110111000101)_2=(1.46514892578125)_{10}=1.46514892578125=\frac{24005}{2^{14}}$」
詳細資料

註3:(感謝pr3pony)
其實 C++ 並無規定負數的實作方法
常見的方法有三種:two's complementone's-complementsign-magnitude
第三篇提到的方法屬於「two's complement」(感覺也是最常見的方法(?) )

註4
電腦學過C++,很聰明地解決了這個問題
電腦會在字串的後面補上一個特殊字元「'\0'」,這個特殊字元我們稱作「結束字元」,對應到的數字是「0」
這樣就可以知道這個字串的結尾在哪裡了
p.s. 「結束字元 ('\0')」也是一種「隱藏字元」
關於結束字元的中文資料(維基百科)
原文詳細資料

註5:(感謝李旺陽學長)
這個規則是C++被定義明確的標準規範
詳細資料

註6
事實上,以現代的觀點來看,「float」的誤差太大
因此一般計算我們會習慣使用增強版float--「double」
除非記憶體不足或使用到GPU運算,不然float很少會被用到
但是因float的輸出入單純許多,本教學以「float」作為新手們學習浮點數的進入管道

註7:(感謝uzk)
實際上,在C++的標準裡面
「int a[n];」裡面的「n」只能是常數 (而非變數)
這裡我們能夠使用一個變數來當作陣列的長度
是因為我們的編譯器是GCC
當使用的編譯器非GCC時 (雖然這種情況較少見),宣告陣列時不能使用變數當作長度

註8:(感謝李旺陽學長)
宣告的部分跟語法解析有關
有逗點的用的是這條
decl-specifier-seq init-declarator-list;
重點在 * (or & && etc) 是一個 Declarators 不是 Specifiers
 int * p ;
被解析為
Specifiers : int
Declarators : *p (Pointer declaration)
int * p , q;
被解析為
Specifiers : int
Declarators : *p (Pointer declaration) , q ((int var) Names declaration)
以哲學觀點

註9 (全範圍)
其實,C++在「#include<cstdio>」之後
一定會將「printf」放入「std」命名空間
卻不一定會將「printf」放入全域命名空間
(C則是完全相反)
因此,最好的寫法是把全部的「printf」改成「std::printf」
或者每次include完之後加上一行「using namespace std;」
資料來源

註10:(感謝李旺陽學長)
C++小數的捨去有更精確的定義是「Round towards zero (向0靠攏)」
超級超級超級詳細的資料 (第99頁 (頁碼85),Floating-integral conversions)

註11:(感謝奕均的留言)
「\」後面接甚麼會發生甚麼事
來解答囉~
「\a」聲音 (例如:printf("123\a456");)
「\b」退格鍵 (例如:printf("123\b456");)
「\e」ASCII碼是27 (16進位:1b),在黑色視窗會顯示一個向左的箭頭,我也不知道為甚麼XD
「\f」ASCII碼是12 (16進位:0c),在黑色視窗會顯示一個女生的符號,我也不知道為甚麼XD
「\n」你知道的
「\r」類似鍵盤上的「Home」鍵 (例如:printf("1234\r56");)
「\t」類似鍵盤上的「Tab」鍵 (例如:printf("123\t456");)
「\u」後面加4位數的16進位數字,會變成該Unicode碼對應到的字元 (例如:printf("\u001b");)
「\v」ASCII碼是11 (16進位:0b),在黑色視窗會顯示一個男生的符號,我也不知道為甚麼XD
「\x」後面加2位數的16進位數字,會變成該ASCII碼 (或Unicode碼) 對應到的字元 (例如:printf("\x1b");)
「\E」和「\e」的效果一樣
「\U」後面加8位數的16進位數字,會變成該Unicode碼對應到的字元 (例如:printf("\U0000001b");)
「\%」和「%」的效果一樣
「\(」和「(」的效果一樣
「\[」和「[」的效果一樣
「\{」和「{」的效果一樣
「\\」會輸出「\」 (例如:printf("123\\456");)
「\'」和「'」的效果一樣
「\"」會輸出「"」 (例如:printf("123\"456");)
「\?」和「?」的效果一樣

注意:
「\n」雖然說類似鍵盤上的「Enter」鍵,但其實在非常非常特殊的情況下,「\n」並不等於鍵盤上的「Enter」鍵,反而比較像「↓」方向鍵 (例如:printf("123\r78\n56");)

註12
這裡介紹的for迴圈功能僅限C++
C語言也有for迴圈,但功能受限,並不像C++的for迴圈這麼好用

註13
可能會有人覺得奇怪,「char」不是用來表示「一個字元」的嗎?為甚麼會被歸類在「整數」呢?
事實上,「char」的儲存和運作方式跟其他整數型別一模一樣
只是「char」的「數字範圍」很適合用來表示英文字母、數字和一些符號等等的字元而已,所以「char」就莫名其妙被用來「表示字元」了XD

註14
這樣的struct定義方式無法在 C (而不是C++) 使用
C的struct必須使用更迂迴的方式來定義:

typedef struct
{
    float a,b,c;
}Line;

這相當於C++這種定義struct的方式:

struct Line
{
    float a,b,c;
};



下一章 (這要怎麼定義下一章啦喂)

感謝:pr3pony、李旺陽學長、uzk、奕均的留言
(版權所有 All copyright reserved)

沒有留言:

張貼留言

歡迎留言或問問題~
若您的留言中包含程式碼,請參考這篇
如果留言不見了請別慌,那是因為被google誤判成垃圾留言,小莫會盡快將其手動還原