第二章 類型、運算符與表達式
2.1 變數名
規則:變數名由下劃線 + 字母 + 數字組成;第一個必須是字母;大小寫區別;不能與關鍵字相同
通用:
1. 變數名小寫,符號常量名大寫(c語言);
2. 望文知意,直觀可拼讀,最好使用英文
3. 長度符合「min-length && max-information」
4. 命名盡量與所採用的操作系統或開發工具風格一致
5. 不要出現僅僅依靠大小寫區分的標識符
6. 最好不要出現標識符完全一樣的局部變數或者全局變數
7. 變數名字:「名詞」或者「形容詞+名詞」 eg:oldValue
8. 函數的名字:「動詞」或者「動詞+名詞」eg:DrawBox
9. 用正確的反義詞命名具有互斥意義的變數 eg:int minValue; int maxValue;
10. 盡量避免名字中出現數字編號
11. 類名和函數名大寫字母開頭的單片語合 eg:class Node; void SetValue(int value);
12. 變數和參數用小寫字母開頭的單片語合 eg:int drawModel;
13. 常量全大寫,下劃線分割單詞 eg:#define MAX_SIZE 100
14. 靜態變數加前綴s_ static eg: static int s_initValue;
15. 全局變數加前綴 g_ global eg: int g_numPeople;
16. 類的數據成員加前綴m_ member eg: int m_width;
2.2 數據類型和長度
c語言的幾種基本數據類型:
u char 字元型,一個位元組,存放本地字符集中的一個字元
u int 整型,機器中整數的最自然長度
u float 單精度浮點型
u double 雙精度浮點型
在類型前面加限定符,short 與long
short int si;
long int li;
習慣上省略int,直接 short s;
short 通常16位,long通常32位,int可以為16位或者32位;
限定符signed和unsigned限定char類型或任何整型,unsigned類型總是正值或者0,遵守算術模2n 定律(n是佔用的位數);
如果char 佔用8位,則unsigned char取值範圍0到255(0 ~ 28-1),sign char取值範圍-128到127(-27 ~ 27-1)
long double 表示高精度浮點數,同整型一樣,長度取決於具體機器
2.3 常量
1234 -- int類型
123456789L -- long類型,後面添加L或者l
如果一個整數太大無法用int類型時候,也被當作long
無符號常量 -- u或者U結尾 12U
ul或者UL表示unsigned long類型
123.4 或者1e-2 -- 浮點數
無後綴也就是默認為double類型,123.4f表示float類型
整型八進位 -- 前綴0 eg:045
整型十六進位 -- 前綴0x或者0X eg:0x1f
一個字元通常是一個整數,單引號括住字元,eg:』A』 ,值對應於ASCII值
轉義字元:』\n』表示換行
『\ooo』 ooo為1~3到八進位數字
『\xhh』 hh為一個或者多個十六進位數字
『\0』表示值為0的字元,空字元null
常量表達式僅僅只包含常量的表達式,編譯時候求值
#define MAXLINE 1000
char line[MAXLINE+1]
字元串常量:字元串字面值,雙引號括起來
「 I am a string」
「」 // 空字元串
字元串常量 == 字元數組,字元串內部表示使用了一個空字元』\n』作為串的結尾。因此,存儲字元串的物理存儲單元數比在雙引號中的字元多一個字元數,標準庫strlen(s)返回字元串s的長度,不包括末尾的\0空字元
『x』 和」x」 是不同的:前者是一個整數,ASCII值;後者是一個字元+一個結束符\0的字元數組。
枚舉常量:另一種類型的常量,枚舉是一個常量整型值的列表
eg:enum boolean {NO, YES} ;//無顯式說明情況下,第一個枚舉名值為0,第二個1
enum escapes {BELL = 『\a』 , BACKSPACE = 『\b』 };
enum months {JAN = 1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT,NOV, DEC};
2.4 聲明
變數:先聲明後使用,聲明 -- 指定一種變數類型
eg:int lower, upper, step;
在聲明中同時對變數進行初始化;eg:int i = 0;
如果變數不是auto則只能進行一次初始化操作;初始化表達式必須為常量表達式
默認下,外部變數和靜態變數被初始化為0;未經顯式初始化的自動變數為未定義
任何變數的聲明都可以const限定符修飾。修飾的變數值不能改變。const修飾的數組所有元素的值不能被修改。
eg:const double e = 2.718;
const char msg[] = 「warning」;
配合數組參數使用,表明函數不能修改數組元素的值
eg:int strlen(const char[]);
2.5 算術運算符
二元:+ - * /(整型會截斷小數部分) %(取模、取餘數,不能用在浮點數)
2.6 關係、邏輯運算符
> >= < <= 優先順序相同,僅次於相等性運算符
== !=
關係的優先順序比算術低 i < lim-1 等價於 i <(lim-1)
邏輯:&& 和|| 具有短路特點,從左到右求值,&&比||優先順序高,兩個都比關係運算符和相等運算符低
關係表達式或邏輯表達式中,如果關係為真則表達式結果1,若假結果0
邏輯運算符!的作用的將非0的操作數轉為0,將0轉為1
if(! valid) === if(valid == 0)
2.7 類型轉換
一般來說,自動轉換是把比較窄的數轉換為比較寬的數。並且不丟失信息的轉換。
eg:f+i 將整型變數i的值自動轉換成float
//eg: 將數字字元數組轉化為整型
int atoi(char s[]) { int i, num = 0; for(i=0;s[i] >= '0' && s[i] <= '9';i++) { num = num * 10 + (s[i] - '0'); } return num; }
//大寫字母轉成小寫
int lower(int c) { if(c >= 'A' && c <= 'Z') return c + ('a' - 'A'); else return c; }
注意:標準頭文件<ctype.h>中定義了一組與字符集無關的測試和轉換函數。
eg:判斷是否為數字isdigit() 與 c >= 『0』 && c <= 『9』
c保證了機器的標準列印字符集中的字元不會是負值,因此表達式中的字元總是正的。
如果沒有unsigned類型操作數,按照以下規則:
n 如果一個是long double 則另一個轉為long double
n 如果一個是double,則另一個轉為double
n 如果一個是float,則另一個轉為float
n 將char與short轉為int
n 如果其中一個為long,則另一個轉為long
使用float為了節省空間或者節省時間,表達式中的float類型的操作數不會自動轉為double。
當表達式中有unsigned類型,帶符號與無符號之間的比較運算不一樣,取決於機器整數類型的大小。
字元類型轉化為int
把較長的整數類型轉為較短或者char時候,超出的高位捨棄
函數調用:參數傳遞給函數時候,char與short轉為int,float轉為double,所以調用函數的參數類型為char或者float時候,也把函數參數聲明為int和double
強類型轉換進行顯式轉換:(類型名)表達式,只是生成一個指定類型n的值,n本身的值並不改變( sqrt((double) n ) )
2.8 自增運算符與自減運算符
++:變數+1
--:變數-1
++n:先將n+1,然後再使用n的值
n++:先使用n的值,再n+1
兩個運算符只能作用於變數。
eg:刪除字元串s中出現的所有c字元
void squeeze(char s[], int c) { int i, j; for(i = j = 0;s[i] != '\0';i++) { if(s[i] != c) s[j++] = s[i]; } s[j] = '\0'; }
eg:字元串拼接strcat(char s[], char t[]) 將t字元串拼接到s的尾部
void strcat(char s[], char t[]) { int i,j; i = j =0; while(s[i] != '\0') //find end of s { i++; } while((s[i++] = t[j++]) != '\0') //copy t { ; } }
2.9 按位運算符
c語言提供6個位操作運算符,只能作用於整型,即帶符號或無符號的char,short,int,long。
& 按位與and
| 按位或or
^ 按位異或xor
<< 左移
>> 右移
~ 按位求反
&:屏蔽某些二進位位 置0
| :置1
^:相同為0 相異為1
a << b :將a的值左移b個單位,b為整型非負,右邊空出的用0填補,等價於對做操作數乘以2的b次方
a >> b : 將a的值右移b個單位
如果a是unsigned,左邊空出的部分用0填補
如果a是signed, 算術移位:左邊空出的部分用符號位填補,邏輯移位則用0填補
eg: 把x的最後六位設置為0 x = x & ~077
2.10 賦值運算符與表達式
i = i + 2 等價於 i += 2;
op= : + - * / % << >> & ^ |
注意:x *= y+1 ; === x = x * (y+1);
賦值表達式的類型是它的左操作數的類型,值是賦值操作完成後的值
eg: 統計參數值為1的二進位位的個數:比較值最後的那位是否為1,然後右移數
int bitcount(int i) { int count = 0; while(i) { if(i & 1) count++; i = i >> 1; } return count; }
eg: 統計參數值為1的二進位位的個數:i & (i-1)結果為去掉i的最後那個1
int bitcount2(int i) { int count = 0; while(i) { count++; i = i & (i-1); } return count; }
2.11 條件表達式
expr1 ? expr2 : expr3
//首先計算expr1,若值不等於0的(為真),計算expr2值,並把該值作為條件表達式的值;否則(為假),計算expr3的值,把值作為表達式的值。
eg:z = (a > b) ? a :b; // z =max(a,b);
注意:如果f是浮點類型,n為int
那麼 (n >0) ? f : n 是浮點類型,與n的值是否為正無關。
2.12 運算符優先順序和求值次序
同行中優先順序相同,各行從上往下逐行降低。