AaronYang風格就是:不講老生長談的東西,挑主題內難懂的地方細講,其他總結一筆帶過,有口訣教口訣,樣本實踐出來,文章內容充實。
本文原理理解性方面的較多,但是都被我用gif圖片(自己photoshop做的)講解
更底層的東西,我自己都不懂的,不可能拿出來講的
本文是針對有學過其他程式設計語言的來學的,有很多地方我跳過略講,所以這不是一篇入門的文章
我在看C的時候,其實發現了一些挺好玩的東西,比如宏替換,帶符號,不帶符號的類型。C的常量定義也不一樣。
重點講位元運算符的運算,還有逗號運算子
最主要是每個類型佔了多少個位元組的理解,以後最佳化程式可以用到。
要避免不必要的類型轉換
精彩預覽:
比如課外知識,很多人知道怎麼去寫編程,但原理知道的很少,知道怎麼用,比如作業系統32位和64位的關於編程方面的區別
這裡講的很容易理解,自己做了些圖片方便理解,如果想直接看,就在本文末最後一節,呵呵
資料類型基本一覽
我學C#的,無符號類型和指標沒怎麼接觸過
其他概念:
開啟程式時候,資料會存在記憶體中(個別可能在寄存器中),我們要對每個資料在記憶體中分配若干個位元組,用於存放資料。資料所佔用的記憶體位元組數稱為該資料的“資料長度”。所以我們要定義不同的資料類型,來安排合適的長度去分配資料存放。於是我們需要資料類型這個概念,不知道有沒有聽懂了
常量
(一) 整型常量
- 十進位:平常的數字寫法,0,22,+11,-3
- 八進位:0開頭的書寫形式,例如00,+08,-033,021
- 十六進位:0x開頭的書寫形式,例如0x1,-0x121,+0x12,0x21
佔用位元組:一般微型機中佔用2個位元組,不分進位,他們的數值範圍都是十進位的-32768~+32767
長整型常量:範圍 -2147483648~+2147483647,佔用4個位元組。
書寫形式:在整數的末尾加上 l 或者 L 例如: 10L -011L +0x15L
那麼其他的都是短整型常量了。如果整型常量後面沒有字母“L”或“l”,而且超過了短整型常量能夠表示的數值範圍,則自動認為該常量是長整型常量了,例如-32769、 32768、40000都是長整型常量了
總結: 整型常量分短整型和長整型兩種,又分十進位,八進位,十六進位三種書寫形式,使用時,要注意區分。例如,88和88L,數值一樣,但是它們在記憶體中佔用不同數量的位元組;比如 10,010L,0x10雖然是短整型常量,但是表示的整數值不一樣。
(二) 實型常量一般形式
[+ 或者 –] 整數部分 小數點 小數部分
指數形式
[+ 或者 –] 整數部分 小數點 小數部分 e或者E [+ 或者 –] 指數(就是普通的整數)
例如 12.345e3 就等於 12.345乘以10的3次方 就是 12345
12345E-3 就等於 12345乘以10的-3次方 就是12.345
總結: 實型常量在一般的微機中佔用4個位元組,數值範圍都是-10的38次方 到 10的38次方,有效數字是7位
例如: 1.23456789和1.234567是相同的,因為有效數字是7位,所以後兩位是無效的
(三) 字元常量
就是char類型了,C語言中,字母區分大小寫,‘a’和‘A’ 是不一樣的
在記憶體中,每個字元常量都佔用一個位元組,具體存放的是該字元對應的ASCII代碼值。例如 ‘a’‘A’ ‘1' ‘%’ ‘\r’ ‘\x3d’在記憶體中的位元組中存放的分別是十進位整數 97 65 49 37 13 61
總結:由於整型常量在記憶體中存放的是整數值,如果其值在0~127之間,C語言規定也可以將其看成一個字元型常量,就是數字當符號使用。例如:整型常量111、70、40可以當做字元常量 ‘o’ ‘F’ ‘(’ 來使用
有個好玩的例子: ‘a’+5 這裡a就會被當做97使用,所以等於結果值102,在C#中我也試過了,也是如此
(四) 字串常量
就是字串,在C#中是string定義的
但是C中定義字串不是用string的,以後說吧.
例如“aAbBcCdD” 逸出字元 \
字串長度
普通的不說了,說點特殊的,例如 “ ”是0, “\\ABCD\\”是6, “\101\102\x43\x44”是4
雖然每個字元在記憶體中只佔用1個位元組,但C語言規定,每個字串在記憶體中佔用的位元組數等於字串的長度+1,其中最後一個位元組存放的字元為“Null 字元串”,其值為0,書寫的時常用逸出字元“\0”來表示,在C語言中稱為字串結束標記。例如:字串“AB”和 “A”的長度分別是2和1,但他們在記憶體中分別佔用3和2個位元組,所以 “A”和 ‘A’是不同的,一個佔用2個位元組,一個佔用1個位元組
關於這個在C#是否是這樣的,我不清楚…
(五) 符號常量
#define 符號常量 常量
C編譯器將在程式編譯前將所有的符號常量自動替換成對應的常量
變數規範 名字全部用大寫字母
例如 #define PI 3.1415926 效果同於C#的 const double PI=3.1415926
#define A ‘A’ 效果等同於C#的 const char A=‘A’
宏定義命令的一般格式如下: #define 宏名 一串符號
宏名就等同於變數名,那個一串符號,你可以理解為對應的值
宏替換就是 把名字替換值,然後進行處理。由於宏替換是在編譯前進行的,所以宏定義命令屬於C語言的”先行編譯命令”
基本例子,理解替換的過程
#define PI 3.14159
#define R 10
#define D (R+R)
#define L PI*D
若程式中用到了L
①先替換成 PI*D
②再將PI替換成3.14156、D替換成(R+R),結果就是3.14159*(R+R)
③這裡面還有宏名,再替換R,最後結果就是 3.14159*(10+10)
下面是1個特殊的例子:
例子: #define PI 3.14159
#define R1 2+3
#define R2 (2+3)
若求 2*PI*R1的值 宏替換結果是”2*3.14159*2+3”
若求 2*PI*R2的值 宏替換結果是”2*3.14159*(2+3)”
變數
定義模式跟C#基本一樣
類型 變數名=值
類型 變數名
算了,直接舉例子
int i;
float i,j;
unsigned short me;
long a1=11L;
unsigned short a1=0111,a2=0x11;
int i=1,j=2,k;
int i,j,k=10;
char c1=‘A’,c2,c3=‘a’;
有名常量的定義(就是C#中的const)
在C#中用 const 類型 名稱定義的,變數規範都是一樣的,名字用全部的大寫字母
C中如下:
const 資料類型符 變數名1=初值,變數名2=初值2 等;
跟C# const一樣
例如 const char FALE='男',FEMALE='女';
一旦定義,程式啟動並執行時候就不許修改了,否則報錯
運算子(跟C#基本一樣,多了幾個,這裡假設你已經學了其他程式設計語言)
運算子感覺最基本的
加 減 乘 除 求餘數 + – * / %
加號或減號 + -
關係運算子 < > <= >= == !=
還有 就是 ! && ||
三元運算子(書中寫的三元,二元都是三目,二目,我不太習慣) ? :
其他符號像 賦值= 逗號 , 數組中的[ ] 其他基本的 括弧 ( ) 遞增的 ++ --
運算完賦值相關的+= -= *= /= %=
資料長度運算子(sizeof),這個C#中沒有
關於成員運算子,我們在C#中,都是 對象 點(.)出來對象中的屬性或者方法的,C中用-> 和 . 關於->在PHP中也是用這個的
指標運算子,C#中應該沒有吧(& * + – )
比較難理解的有 位元運算符(例如<< >> ^ ~ & | &=等),其實C#中也有,我們很少用,過一會講解一下這個
運算相關的還有 就是 結合性,運算的優先順序 這個概念
我以前在 Javascript講過,語言邏輯都是通用的,那裡講的比較詳細 點擊查看
一、基本常見的跳過了
二、長度運算子(sizeof)
開啟C-Free5
sizeof 是C裡面的關鍵字 並非函數,意思是c 所佔的記憶體多少 單位是位元組
getch(); 用此命令可以在啟動並執行的時候,按任意鍵退出 ,如果沒有此命令,螢幕閃一下就沒了(程式結束就退出) 所以看不見結果
等同於C#中的Console.ReadLine();
重點講解一下 位元運算符
編程中: 0代表false,假,1代表true,真,有句口訣,非0即真
一、位邏輯運算子
使用數目和位置 物件類型 結果類型 結合性
位非 ~ 單目首碼 整型 整型 自右向左
位與 & 雙目中綴 整型 整型 自左向右
位或 | 雙目中綴 整型 整型 自左向右
按位加 ^ 雙目中綴 整型 整型 自左向右
關於16進位轉2進位的對照表格
【例一】
設變數定義如下: unsigned short a=0111,b=0x53
先把 a 無符號八進位轉換成二進位: 0000 0000 0100 1001
b 無符號十六進位轉換成二進位: 0000 0000 0101 0011
①~a 把二進位是0的位置變成1,是1的變成0(對應的二進位就是1111 1111 1011 0110),然後轉換成八進位為0177666,運算後a不變
②a&b,兩兩位對應,有0則0,對應的二進位是(0000 0000 0100 0001),然後轉換成八進位為0101,運算後a不變
③a|b,兩兩位對應,有1則1,對應的二進位是(0000 0000 0101 1011),然後轉換成八進位為0133,運算後a不變
④a^b,兩兩位對應,相異則1,對應的二進位是(0000 0000 0001 1010),然後轉換成八進位為032,運算後a不變
二、位移位元運算符
使用數目和位置 運算規則 物件類型 結果類型 結合性
左移 << 雙目中綴 a<<b.a向左移b位 整型 整型 自左向右
右移 >> 雙目中綴 a>>b.a向右移b位 整型 整型 自左向右
移位時,移出的位元全部丟棄,移出的空位補入的數與 左移還是右移有關
如果是左移,則規定補入的數全部是0,;如果是右移,如果不帶符號,則補入的數全部是0;如果帶符號,則補入的數全部等於原數的最左邊位上的數(即原數的符號位)
下面假設a已經是轉換成二進位的,原本本來a=47,現在轉換成了二進位101111
無符號左移,帶符號左移,他們兩個一樣的,我做張圖片示範
無符號右移
帶符號右移
帶符號右移(最左邊是0,就補0,最左邊是1,就補1)
移動完後,在將二進位轉換成十進位,這就是位移位元運算符
三、位自反賦值運算子
功能類似常用的 += -=,運算完了,改變原有的值
主要是這5個: &= |= ^= <<= >>=
這裡不講了,就是經過位移運算後,改變原有的值,第一部分,第二部分講的都是運算後不改變原有的值
運算式(跟C#90%一樣)
- 算數運算式
- 關聯運算式
- 邏輯運算式
- 賦值運算式
- 逗號運算式
- 條件運算式
重點講一下,C#中沒有的 逗號的特殊用法,可以組成逗號運算式
逗號除了聲明變數時 int a,b=10,還有函數參數也是用逗號來間隔的
但是那裡的逗號都不是運算子,在C中,逗號可以是一種運算子。下面我們通過幾個例子學習一下
逗號運算子,用它可以將兩個運算式串連起來。如:
3+5,6+8
稱為逗號運算式,又稱為“順序求值運算子”。逗號運算式的一般形式為
運算式1,運算式,運算式3……運算式n
最終的結果都是以最後一個運算式的值為準,也就是運算式n的值
例如上面一個逗號運算式的值就是6+8,也就是14
例一
這裡先算3乘以5等於15,然後把值賦給了a,a等於15了,然後15乘以4,最終整個運算式的值就是60了
例二
C語言表達能力強,其中一個重要方面就在於它的運算式類型豐富,運算子功能強,因而c使用靈活,適應性強
類型轉換的小例子,提醒最佳化(變數=運算式)
C#中有強制轉換和隱式轉換,C也有,自動轉換規則和強制轉換規則,99%和C#一樣
運算式計算中資料類型的自動轉換規則 :參加運算的各個資料都轉換成資料長度最長的資料類型,然後計算-----”就長不就短“。
例如:
運算結果存入變數時資料類型的自動轉換規則 :先將運算結果的資料類型自動轉換成左邊變數的資料類型,然後再賦予該變數-----”就左不就右“。
例如:
運算結果的強制性資料類型轉換規則 :跟C#一樣,例如 (int)14.5 即 14
例如:
避免轉換的小例子
例如:
課外知識
一個位元組等於8個二進位位;即 1byte=8bit
電腦採用二進位的,8=2^3,通常最高位為符號位
位元系統中,每個0或1就是一個位(bit),位是資料存放區的最小單位。其中8bit就稱為一個位元組(Byte)。電腦中的CPU位元指的是CPU一次能處理的最大位元。例如32位電腦的CPU一次最多能處理32位元據。
Bit,乃BInary digit(位元)位的縮寫,是數學家John Wilder Tukey提議的術語(可能是1946年提出,但有資料稱1943年就提出了)。這個術語第一次被正式使用,是在香農著名的《資訊理論》,即《通訊的數學理論》(A Mathematical Theory of Communication)論文之第1頁中
所以說64位作業系統,每次讀取的位元更多,所以處理資料更快了,但可能存在相容性的問題下面講一個小題目了
回憶本篇第一部分
short類型的位元組長度2
long類型長度是4
下面用圖片解釋一下
變數b3是4位元組的,存放65536後,對應的二進位位元如下:
將b3的值賦予變數a的時候,b3的4位元組中低16位元據(右邊2位元組)組成的新值就賦予變數a了,最後轉換成十進位顯示,就是0
學習總結
- 對常量,宏替換,變數 原理性的理解和使用
- 資料長度,進位轉換的理解
- 位元運算符的理解和使用
- 逗號運算子的使用
- 佔用位元組數的理解和實踐