變量
限制:1.字母+數字 ? (第一個字符必須為字母)?
2."_"視為字母 ?一般情況是 _使用在命名較長的變量命中以提高名字的可讀性 ?例如:first_const 起到駝峰命名的作用 ? ?例程中的變量名一般使用 _ 開頭命名 所以我們在命名時不要使用_ 開頭
3.區分大小寫 ? 變量名一般小寫 ?符號常量名全部大寫
4. 內部名:只在自身.c文件中使用的 命名標識符 長度最長為31個字符 (這一部分存疑,沒有試出來)
外部名:用于不同.c 文件調用的函數名,變量名 有效識別長度為6位 且不區分大小寫 , 需要保證6位字符的唯一性 ? baf ?baF 在調用時將被視為同一外部鏈接 ??
5.原則 : 命名要盡量重表面即可看出 變量或函數的用途 ?局部變量也盡可能簡潔短小
數據類型及長度
char ? ? ? ?字符型 ? ? 占一個字節
int ? ? ? ? ? 整型 ? ? ? ?通常反應機器中整數的最自然長度
float ? ? ? ?單精度浮點類型
double ? ?雙精度浮點類型
在i基本前加限定符(這是int 可以省略) ??
short ?int sh;---->short sh; ?short <=int 長度 ?至少為16位
long ?int sh;---->long sh; ?long 類型至少為32位?
long double ;?
類型限定符 signed ?與 ?unsigned 用于限定 char 類型或任何整型 (char ? short ?int long) 不包括浮點型
這里介紹兩個計算基本類型所占空間的 頭文件
sizeof() ?返回 基本數據類型的 長度(字節B)
1B(Byte 字節)=8bit,
1KB (Kilobyte 千字節)=1024B,?
1MB (Megabyte 兆字節 簡稱“兆”)=1024KB,?
1GB (Gigabyte 吉字節 又稱“千兆”)=1024MB,?
1TB (Trillionbyte 萬億字節 太字節)=1024GB,其中1024=2^10 ( 2 的10次方),?
1PB(Petabyte 千萬億字節 拍字節)=1024TB,?
1EB(Exabyte 百億億字節 艾字節)=1024PB,?
1ZB (Zettabyte 十萬億億字節 澤字節)= 1024 EB,?
1YB (Yottabyte 一億億億字節 堯字節)= 1024 ZB,?
1BB (Brontobyte 一千億億億字節)= 1024 YB.
常量
預編譯處理器形式定義 ?#define
常量定義 : ?#define ?名稱 ?+ 值(又稱為 宏定義) ? ?
#define ?LENGTH ?10;
#define ?WIDTH ?5;
#define ?NEWLINE ?'\0';
const ?關鍵字 定義
const ?+ ?類型 ?+ ?命名 ?= 值
const ?int ?LENGTH = 10;
const ?int ?WIDTH = 5;
const ?char NEWLINE = '\0';
兩種方式有什么異同:
1. 編譯器處理方式
? ? ?define 常量是在預編譯是進行 賦值的的
? ? ?const 是在編譯時進行賦值的
2. 類型檢查
? ? ?define 不聲明常量類型 ?編譯器不進行類型檢測 比較危險 ? ??
? ? ?const 需要進行類型聲明 ?并對常量值是否匹配類型進行檢測
3. 內存空間
? ? ?define - 不分配內存 ?給出的是立即值 有多少次使用就進行多少次替換,在內存中有多個拷貝,消耗內存較大
? ? ? const - 在靜態存儲區中分配空間 ?在程序運行過程中內存中只有一個拷貝
4. 其他
在編譯時 ?編譯器通常不為 const 常量分配存儲空間,而是將他們保存在符號表中,使得他成為一個編譯期間的常量,沒 ?有了存儲與讀內存的操作,使得它的效率也很高
宏定義的作用范圍僅限于當前文件
默認狀態下 ?const 對象只在文件中有效 ?當多個文件中出現 同名的const常量 那么意為著定義了不同的const對象
想在其他文件中使用一個const 常量 需要使用 extern 聲明該常量
define 可以有const 完全替換 ? 最好使用 const 常量
類似1234 的整數常量屬于int 類型 ?long類型的常量以字母l或 L結尾,123456789L
如果整數太大無法用int 處理時 ,將會被當做long類型處理 ?
無符號常量以字母u或U結尾 ? 后綴ul 或者UL 表示無符號的long類型
整型的八進制 十六進制表達?
帶前綴0的整型為八進制 ?前綴為0X或0x,則表示它為16進制
字符常量:
一個字符常量是一個整數 ,書寫時將一個字符放在單引號中‘x’
字符在機器字符集中的數值就是字符常量的值 可以參見ASIIC碼值
比如 '0' ?的值為48 ?
某些字符可以通過轉義字符序列表示為字符和字符串常量 ? 轉義字符看起來像兩個字符 一般由 ?' '單引號+ \ +字符組成
例如 ?'\ooo' ?表示任意的字節大小的位模式 ? ?其中 ?ooo 代表1-3 個八進制數字(0....7) 這種為模式還可以用'\xhh'
所以 \000 表示八進制 ? \xhh 表示16進制數
'\071' 表示一個字符 對應的只為 ?7*8^1+1*8^0 = 57
‘\0’字符常量 ?表示值0的字符,也是空字符null ?
常量表達式 ? 僅僅由常量包含的表達式 ? 這種表達式在編譯的時候求值而不是在運行時求值
#define MAX 1000
char line[MAX+1];
字符串常量 ?也叫字符串字面值 ? 是雙引號括起來的字符序列
例如:“I am ?a ?string”
或者 ?"" ?空字符串
雙引號不是字符串的一部分 它只是用來限制字符串的 ? 字符常量中使用的轉移字符常量在字符串中仍然可以使用?
字符串常量就是字符數組 ? 字符串內部使用一個空字符'\0'作為串的結尾
存儲字符串的物理存儲單元要比“”號括起來的字符 多一個?'\0' 的結束字 (在存儲的時候編譯器自動添加該'\0' 如果字符串結尾沒有添加)
標準庫中 strlen() 計算字符串長度是 空字符是不計入其中的'\0'
字符常量 與 字符串常量的區別
首先字符常量由' ' ?包裹 ? 字符串常量由 " " 包裹
那么 'c' 與 "c" ?里一個區別 'c' 存儲是為單個字符 ?“c” 存儲是 是兩個字符 ?字符c 與?'\0'
枚舉常量? ? 是另外類型的常量?
組成 ? ?enum + 名稱 ?+ { 枚舉值 } +;?
enum boolean {NO,YES}; ? boolean ?中的 第一個值NO 為0 ? ?第二個值為 1;
如果沒有特殊說明 ?那么 枚舉{} 中的第一個值 為 0 第二個值為1 ? 依次類推
enum months { JAN = 1,FEB,APR } ?
第一個JAN 為1,FEB =2 ?APR =3 ?默認值根據第一個枚舉值一次加1
不同枚舉類型的名字必須互不相同 ? 同一枚舉中 的枚舉值是可以重復的?
例如 : enum months { JAN = 1,FEB = 1,APR = 3 }
c語言中枚舉類型如何使用
#include <stdio.h>
enum java{
? ? day,
? ? other,
? ? app
};
int main() {
? ? ?enum java ik = -12; ? ? ? //這里 聲明的枚舉變量能不能取值在 枚舉值之外 依賴于編譯器是否對枚舉類型值 進行嚴格的檢驗?
? ? ?printf("data----->%d",ik);
? ? ? printf("data----->%d",day); ? ? ?//能夠當常量使用 ? 直接可以打印出 day的值 ? day初始值為0
? ? ?return 0;
}
一般情況下 我們需要將值取在 ?enum java{ ?} 范圍內 ?以為這樣是一定不會報錯的
初始化枚舉k 同時聲明a 變量
enum k {day=1,day1,day2} a;
2.4 聲明
所有變量都必須進行聲明,然后才能使用,一個聲明指定一種變量類型,后面跟的變量表可以包含一個或者多個該類型變量比如 int ?a,b, c,d,e; 聲明了 五個int類型的變量
他也等價于 ?int a; int b; int c; int d; int e;
初始化
如果變量名后面緊跟一個等號 以及一個表達式,該表達式就充當對變量進行初始化的初始化表達式
char ?esc = '\\';
int i = 0;
int limit = MAXLINE+1;
float eps = 1.0e-5;
1.如果變量不是自動變量(局部變量),則只能進行一次初始化操作
2.同時初始化表達式只能是常量表達式
const 限定修飾符修飾的變量 ,其變量的值是不能修改的,如果限定符修飾的是數組 則數據中的所有值都不能被修改
const ?double ?e ?= ?2.718218245905;
const ?char ?msg[ ] = "warning: ?";
2.5 算術運算符
二元算術符包括: + ?- ?* ?/ ?%(取模運運算符) ?
表達式: x%y
的結果是 x 除以 y 的余數,當x能被y整除時,其值為0?
+ ? - ??* ? / ? % ?的計算優先級與我們課本上學習的優先級一致,從左到右 先乘除后加減
但是對于一元運算符 ? ?k++ ? k-- ? ++k ? --k ? ?他們的優先級是要高于 加減乘除
2.6 關系運算符與邏輯運算符
關系運算符包括下列幾個運算符:
> ? ? ? ? ? ? ? ?>= ? ? ? ? ? ?< ? ? ? ? ? ?<=
他們具有相同的優先級 ?優先級僅次于 == ?!=
關系運算符的優先級比算術運算符低 ? ?i< lim -1 ?等價于 ?i<( lim -1 )
邏輯運算符&&與||有一些較為特殊的屬性,由&&與||連接的表達式按從左到右的順序進行求值 ? ?
得到結果為真或假后立即停止計算
if(表達式1 || 表達式2){
? ? ? ? ? xxxxxxx;
}
如果表達式1 為真 ? ?表達式2 就不進行判斷了 ?直接執行 xxxxx
if(表達式1 && 表達式2){
? ? ? ?xxxxxxxx;
}
YYYYYYY;
如果表達式1為假 ?表達式2 就不知行了 ? 直接跳過if的{} 執行下面的代碼 YYYYYY
優先級 : ? (k++ ? k-- ? ++k ? --k) 一元加減??> 乘除法 > ?加減法 ?>? (== ?!=) ?> ?(?> ? ? ? ? ? ? ? ?>= ? ? ? ? ? ?< ? ? ? ? ? ?<= ) ?> ?&& ?> ||
c語言中 邏輯表達式的值為1 表明關系為真 ? 如果值為0 則關系為假
2.7 類型轉換
包括 自動轉換 和 強制轉換
自動轉化: 一般來說 ?自動轉換 是指把 比較窄的 操作數轉換為 比較寬的操作數,
當然較寬的操作數也可以轉換為較窄的操作數,這可能會造成精度的缺失,編譯器會給我們發出警告,但這并不是非法的不可接受的
自動轉換不需要我們人為轉換,編譯器自動轉換
強制轉換:(類型名)表達式 ? ? ?比如 char a = 90; ? (int)a ?+ 1 =91;
如何正確理解強制轉換:表達式首先被賦值給類型名指定的類型的某個值,然后在用該變量替換上述整條語句
(int )a -----》 ? int ?w(強轉類型的某個變量) ?= (int)a (a轉型后的值)
w+1 = 91;
a自身的值是不改變的 ?而是 編譯器創建了一個新的變量來承接 a強轉的值
2.8 自增運算符與自減運算符
int n =5;
1. x ?= ?n++; //先賦值 后 ++ ?
2. x ?= ?++n; //先++ 后賦值
?1處的x值應該是 ?5
? 2處的x值應該是 6
最終n的值都為 6
2.9 按位運算符?
& ? ?按位與 ? ? ? ? ? ? ?----------------》規則 ? ?1&1 =1 ? 1&0 =0 ? ?0&0 = 0
| ? ? ?按位或 ? ? ? ? ? ? ? ----------------》規則 ? 1|1 = 1 ? ?1|0 = 1 ? ? 0|0 =0
^ ? ? 按位異或 ? ? ? ? ? ?----------------》規則 ? ?1^1 =0 ? ?1^0=1 ? ? 0^0 =0 ?相同為0 不同為1
<< ? 左移 ? ? ? ? ? ? ? ? ??
?---------------》規則 ? ?12<<3 ? ? 左邊轉換為二進制 0000 1100 ?<< 表示向左 ?3表示移動3位 ? 0000 1100和面補3個0? ?得到 0110 0000 ?= 96 ?
相當于 12*2^3 =96 ?一位為2倍
>> ? 右移
--------------》規則 ? ?12>>3 ? ?左邊轉換為二進制?0000 1100 >> 表示向右 3表示移動3位 ???0000 1100 ?砍掉右3位 ?
得 0000 0001 = 1 ? ? ?相當于 12/2^3=1
~ ? ? 按位求反(一元運算符) ------》規則 ? ?~1 = 0 ? ~0 =1 ? ?
~12 ?= ~(0000 1100)= 1111 0011 ? ?
要這些符號干什么用?
位運算主要是控制二進制時使用,目的是節約內存,運算速度更快,對內存要求極為苛刻的地方常會使用
這里有一句順口溜 :清零取反要用與 ? ?某位置1可用或
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 若要取反和交換 ? ?輕輕松松用異或
那么 &與運算 的作用 來看看
1.清零特定位 ? ? ? 對于0111 1111 我想是第3位(低位到高位算) 為0
0111 ?1111 ?& ?1111 ?1011 ? ---》0111 ?1011
&的這個值只要 其他位為 1 ?特定位為0 即可
2.取某數中指定位 ? ??對于0111 1111 我想是第3位(低位到高位算) 是啥
0111 1111 & 0000 0100 ?----》 0000 0100 ??
保證想要的位置為1 其他地方為0 即可
按位或 | 運算作用
將源操作數的特定位置轉換為1 ?其他位置不變 ? ? ?0011 0111 想將第4位 0 轉為1
0011 0111 | 0000 1000 ?---》0011 1111 ?
保證轉換位為1 ?其他位為0
3.異或運算作用 ^
1.使特定位取反 ? ?1變0 ? 0變1?
0111 1111 ?想使第3位 取反為0 ? ? ? ? ? ? ? ? ? ? ? ? ?0111 1011 ? ? ? ? ??
0000 0100 ? ----》 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??0000 0100
0111 ?1011 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?0111 1111
只要特殊位置為 1 ?其他位置為0 即可
2.交換兩個變量的值
a = 3 = 0011 ?b = 4 = 0100 ? ? ? ? ? ? ? ? ? ? ? ? ??
1.a = a^b ? ? ? ? ? ? ? ? ? ?---> 0011 ^ 0100 = 0111 =a
2.b=b^a ? ? ? ? ? ? ? ? ? ? ?---->0100 ^ 0111 = 0011 =b
3.a = a^b =4 ? ? ? ? ? ? ? ----->0111 ^ 0011 = 0100 =a =4
2.10 賦值運算符 與 表達式
i = i+2; ? -----> ?i +=2;
+= 在運算中 就被成為賦值運算符
大多數二元運算符 ? (即有左 右兩個操作數的運算符 比如+)都有一個相應的復制運算符 op=,op可以試一下這些運算符之一
+ ?- ?* ?/ ?% ?<< ? >> ? & ?^?
如果 ?expr1 和 expr2 時表達式 ?那么 ??
expre1 ?op= expr2 ;?
等價于 ??
expr1 = (expr1) op (expr2)
x *=y+1; ? 轉化為
?x= x*(y+1);
賦值運算符的有點: 簡便 ? ?但我個人認為 i +=2; 并沒有 i=i+2;來的直觀
2.11 條件表達式
if(a>b)?
? ? ?z=a;
else
? ? z=b;
用來求ab中的最大值 并將結果保存在z中
三元表達式 ?
expr1 ? expr2 : expr3;
表達式expr1 ? ?如果成立執行expr2 ? ? 如果bu成立執行expr3
首先計算expr1的值是否不等于0 ? ? 等于1計算expr2 ? ? ? 等于0 計算expr3
z = ?(a>b)? a : b ? ?a是否大于b ?如果大于b ? ?則 z = a ? ? 如果不大于b ? z = b; ?z仍然去取 ab 間的最大值
關于類型轉化 ?(n > 0)? f : n;
如果f 為 float 類型 n是int 類型 ? 那么 ?表達式是float類型 , 它的類型與 n 無關
條件表達式的優點是:可以使代碼更加簡潔
2.12 運算符優先級與求職次序
& ? ^ ?| 的優先級低于運算符== 與 !=的 ?
所以 ? ?if((x&MASK)== 0) 必須使用( ) ?括起來才行 不然就會先執行判斷再執行&運算
c語言沒有指定同一運算符中多個操作數的計算順序(&& ? ?|| ? ? ?: ? 除外)
比如 ? x = ?f( ) + g( ); ? ? f() ?與 ?g() ?這兩個函數哪個先執行并不確定
c語言中也沒有指定函數個參數的求值順序
prinf(“%d%d\n”,++n,power(2,n));
對于先執行 ++n 還是先執行 powe(2,n) 這是不確定的 與 編譯器有關系
那么避免的方式就是 ?
n++;
prinf(“%d%d\n”,n,power(2,n));
一種令人感覺不舒服的表達方式
a[i] = i++; ? //這里存在一個問題 就是 i 使用的是 原來的值還是 i++ 后的值
這取決于編譯器的抉擇...
所以在我們編寫代碼時要盡量避免這樣的代碼設計,因為他存在極大的不確定性(在不同的編譯器中表現不相同)