NTNUCIC
台師大資訊研究社
對資訊相關有興趣的人都來~~
林品儒
www.github.com/aigecko
師大貓耳控
喜歡Asm,Ruby和Crystal
向電腦發出指令使其服從操作
給電腦看?
給人類看?
編輯:Edit -> 原始碼
編譯:Compile -> 目的檔
組譯:Assemble -> 機械碼
連結:Link -> 執行檔
執行:Run
高階語言
組合語言
機械語言
方便人類撰寫與開發
適合人類閱讀
不適合電腦閱讀
C語言
和電腦的運行關連性較高
適合電腦閱讀
不適合人類閱讀
8d 74 26 00 lea 0x0(%esi,%eiz,1),%esi
8b 54 24 28 mov 0x28(%esp),%edx
89 44 24 04 mov %eax,0x4(%esp)
8b 44 24 20 mov 0x20(%esp),%eax
89 54 24 08 mov %edx,0x8(%esp)
89 04 24 mov %eax,(%esp)
e8 38 06 00 00 call 6b902250 <___mingw_TLScallback>
b8 01 00 00 00 mov $0x1,%eax
83 c4 1c add $0x1c,%esp
c2 0c 00 ret $0xc
超不適合人類閱讀
毫無反應,只是個標記語言
雖然看起來很C但我們還是寫C++
使用GCC和C++編譯器
搭配整合開發環境更方便
整合開發環境
將文字編輯以及編譯除錯的功能整合
DevC++,VS,Code::Blocks
和ATA沒有關係
Code::Blocks
跨平台
開放原始碼
功能多
http://www.codeblocks.org/downloads/26
我都用sudo apt-get install codeblocks
為了廣大使用Windows的社會大眾
還是告訴各位安裝的程序
建議全部安裝
30秒不到就可以安裝完成
#include <stdio.h>
int main(){
printf("hello, world");
return 0;
}
按下F9後編譯執行
記得副檔名要存成.cpp
安裝Code::Blocks
#include <stdio.h>
int main(){
printf("hello, world");
return 0;
}
編譯執行
在程式語言中有一定的語法規範
學習語言有風險詳情請看規格說明書
來說明hello,world是怎麼回事吧~~
在C::B中以綠色呈現
#符號代表程式碼預處理用
在編譯前發揮作用
可以引入函式庫或是定義巨集
int main(){}
程式執行的主要部份
程式執行的第一個函式
別再寫void main(){}了
printf("hello,world");
列印傳入的"hello,world"
記得最後一定要有分號
return 0;
函式中負責回傳結果
在主函式中回傳執行狀況
主函式中可省略
在C::B中以藍色粗體呈現
該單字有特殊意義
不可作為取名之用
變數可以用來裝東西
而裝的東西有分型別
各語言的型別可能略有出入
在C/C++中各型別佔有不同的記憶體空間
名稱可以使用英文數字底線
名稱有區分大小寫
宣告後只能裝指定型態的東西
依照宣告的位置不同能用的範圍也不同
使用變數前需要先宣告
型別放最前面 空白後接著逗號分個的變數
記得變數名稱不可使用關鍵字取名
變數宣告時可以順便初始化
bool isAlive,done=true;
佔用8位元空間
bool僅有兩個值true和false
在C/C++中0為false
非0則為true
不用是bool也可以判斷真假
整數可以是有號或無號
也有不同數字範圍限制的整數
整數運算超出範圍會溢位
十進位可以直接以數字表達整數
八進位使用0開頭且可使用0到7的數字
十六進位使用0x開頭使用數字和A到F
16位元:short
32位元:int,long
64位元:long long int,long
編譯器32或64位元會造成結果不同
16位元:-32768~32767
32位元:-2147483648~2147483647
64位元:真的有夠大的範圍...
-9223372036854775808~-9223372036854775807
雖然很大但還是有爆炸的可能
某個有錢人擲骰子電腦遊戲有個BUG
查21億有錢人NPC的稅
自己會破產~~
只要在有號整數前加上關鍵字
unsigned
就可以讓整數範圍限制非負數
正數的表達範圍變成2倍
某韓國2D樹葉之地形線上遊戲
只要最大血量超過65535
損血後補個血就會死翹翹
整數是有範圍限制的
不論是有號或是無號
一定要保持在範圍內操作以免危險
您一定不希望玩家補血身亡
有不同精準度
float:32位元
double:64位元
long double:96,128位元
其運算原理較複雜不詳述
float約準確到7位 而double則是14位
練習宣告變數的語法
16位元無號整數 s 給予值0755
32位元整數 n 給予值0x5566
單精度浮點數 f 給予值1.23456789
雙精度浮點數 d 給予值-1.602e-19
存放8位元的ASCII字元
char
也可以當8位元的有號整數來用
記住不能放中文...
不要小看中文字的顯示
其中編碼原理在此不講
各位只要知道1個char裝不下...
至少你無法用255種變化表達所有中文字
使用單引號將字元包起來
'A' '0'
再次提醒單引號內只能放一個字元
可以使用有特殊功能的字元
'\0'代表NULL字元
'\\'可以放入反斜線
'\n'代表換行
'\t'代表tab
乍看之下有2個字元實際上只有1個
使用雙引號將多個字元包起來
前面的printf就是將字串列印出來
要把字串裝進變數另有學問...
中文字串問題恕不負責
使用printf傳入字串以及多個值
"%d"對應32位元整數
"%f"對應浮點數
"%c"對應字元
"%s"對應字串"
"%x"輸出16進位32位元記憶體(!)
呼叫格式參考printf("%c%d",'\n',55)
列印之前的變數s,n,f,d
記得變數的型態和字串格式要對應
對於各種數字類型有四則運算可以操作
注意整數間運算只會是整數
浮點數間運算只會是浮點數
整數和浮點數運算會變浮點數
負號 - 在數字前即為負數
可以用小括號將負數包起來
符號 + 代表加法
小心別把數字加爆了
有號整數運算可以加上負數
符號 - 代表減法
千萬別以為減法就不會爆炸...
無號整數減去比該值大的數會暴增
千萬不要使用英文字 x 當乘法
記得是 * 代表乘法
使用 / 當除法
注意看是斜線不是反斜線!!
誠心推薦使用數字鍵盤準沒錯
整數除以0會讓程式崩潰
浮點數除以0則是無限大
雖然名稱叫四則運算但取餘數也是一份子
使用 % 來取餘數
一樣要小心對0取餘數會導致崩潰
使用小括號可以改變運算的優先順序
這個應該不要多說了....
運算以下算式並列印之
1+3*4/2
1/0.0
(1+7)/(4-2)*5
可以試試看用四則運算讓數字超出範圍
電腦和人類的差別在於數字是以位元表示
可以以位元為單位計算
日常生活不常見到的運算
都當成整數進行計算
使用 & 可以將兩個數取AND
兩位元為1才為1
其他結果則為0
使用 | 可以將兩個數取OR
任一位元為1則為1
使用 ~ 前綴將位元反轉
每個位元的0變1 1變成0
稱為INVERT
使用 ! 前綴對整個數字取NOT
非0的數字變成0
0變成非0
注意這個和位元反轉不一樣
使用<<將數字左移指定次數
效果相當於乘以2的次方數
使用>>將數字右移指定次數
效果相當於除以2的次方數
使用 ^ 將兩數取Xor
兩個位元相同則為0
兩個位元不同則為1
用在加密用(當然沒這麼簡單...)
將變數指定值再計算算式並列印之
2*(a&b)+(a^b)
(a&b)+((a^b)>>1)
0xffff&0x3333>>8
前兩個算式有特殊效果
在C/C++中深奧難懂的神祕名詞
代表記憶體的位置
可以取出變數的記憶體位置
或是從指定位置取出值
雖然各種型別佔用空間可能不一樣
但是他們的指標都是一樣大的
可能是32或64位元視編譯器和系統而定
變數名稱前面加上星號*
這樣"該變數"就會是該型別的指標
對變數使用&當前綴的話可以取得其指標
對指標使用*前綴則可以取得該位址放的值
注意地址和放的東西不一定一樣
地址和放的值不會一樣
指標可以指派給變數
#include <stdio.h>
int main(){
int a=0x5566;
int *p=&a;
printf("%X %X %X %X %X",a,p,*p,&a,*(&a));
}
要使用陣列需要使用指標進行操作
宣告陣列要在變數名稱後加上使用[]
陣列宣告時要指定大小
可以用{}將其元素初始化
使用sizeof()傳入變數或型別可得知其位元組數
因為是運算子所以編譯時就知道
也可以用來看陣列多大
可以手動指定大小
也可以把元素指派好後自動知道大小
#include <stdio.h>
int main(){
bool arr[4],table[]={true,false,false};
char list[5]={'a','b','c','d','e'};
printf("%d %d %d",
sizeof(arr)/sizeof(bool),
sizeof(table)/sizeof(bool),
sizeof(list)/sizeof(char));
return 0;
}
字串其實是一種char陣列
但是字串最後的元素是NULL字元
把字串裝進變數可使用陣列宣告方式
char str[]="hello, world"
陣列中的放的東西稱為元素
要取出元素必須要索引代表其位置
索引值從0開始
使用[]來取得指定索引的元素
觀察字串索引以及元素的變化
觀察初始化但未指定的陣列
觀察未初始化的陣列
#include <stdio.h>
int main(){
char str[]="abcdef";
int arr[4]={22,66};
short uninit[2];
printf("%d %d %d\n",str[0],str[5],str[6]);
printf("%d %d %d\n",arr[0],arr[1],arr[2]);
printf("%hd %hd",uninit[0],uninit[1]);
}
陣列的頭可以代表該型態的指標
對於指標可以進行加減法來移動
移動的矩離和該型別的大小相關
加法減法可以使用
還可以使用 ++ 遞增
以及使用 -- 遞減
注意!此兩個運算子是地雷請小心使用
#include <stdio.h>
int main(){
int n=100,m;
m=++n;
printf("%d %d\n",n,m);
m=n++;
printf("%d %d\n",n,m);
}
放前面放後面竟然結果會不一樣
雖然在此不探討其原理
但是記得一個指令一個動作
有遞增遞減就不要指派
愛護生命遠離debugging
可以用來迭代整個陣列
記得陣列本身可以轉成該型別指標
#include <stdio.h>
int main(){
int arr[]={100,200,0};
int *p=arr; \\注意這裡直接把arr給p
printf("%d ",*p);p++;
printf("%d ",*p);p++;
printf("%d ",*p);p++;
}
今天是資訊研究社寒訓的前半段
前半段的課程稍微複雜
希望大家看完直播還是再研究一下投影片
感謝各位的收看
課程網址:ntnucic.github.io/104_winter