聲明,定義和初始化
聲明標(biāo)識符iden是告訴編譯器"有這么一個變量var,具體var里是什么,你自己去看"。聲明只需要標(biāo)識符的類型和標(biāo)識符名字,C語言的任何標(biāo)識符在使用前都需要聲明,當(dāng)然變量也不例外;如果標(biāo)識符的定義代碼在使用之前,那么定義的代碼可以看作是聲明,否則需要聲明定義標(biāo)識符iden是告訴編譯器"這個iden是什么";
初始化標(biāo)識符iden是定義iden時給iden賦值,一個沒有被賦值的iden里面存的是之前這塊內(nèi)存的值,就可能是任意的值,一不小心使用這樣的標(biāo)識符是十分危險的,所以一個好的習(xí)慣是定義一個標(biāo)識符后立即初始化;另外一個原因是常量的值必須在初始化時確定,如果不進(jìn)行初始化,那么這個常量以后永遠(yuǎn)都不能賦值了
通常情況下,當(dāng)我們寫int atom=10;時,就同時進(jìn)行了變量的定義和初始化。
指針
內(nèi)存就是一排大小都是一byte,且自己編號的抽屜。編號即抽屜的地址,里面的東西即抽屜的內(nèi)容
指針即"地址"。即抽屜的編號
指針變量即存儲"標(biāo)識符地址"的變量,即存放了另一個抽屜編號的抽屜,對指針變量"取值"即得到標(biāo)識符的地址,即"指針的指向",對該變量"取址"即該變量本身存放的地址。當(dāng)提及指針的時候,一定要注意說的是一個指針常量(一個地址), 還是一個指針變量,這是國內(nèi)的教材非常差勁的一個習(xí)慣
一個指針變量理論上可以存儲任何標(biāo)識符的地址,但是為了便于管理,C語言把指針變量也按照標(biāo)識符的類型進(jìn)行了劃分。所以有了函數(shù)的指針,字符指針,數(shù)組指針etc. 但他們其實(shí)都一樣,即雖然所有的抽屜的編號都是一張紙條,但某個抽屜只用來存儲裝了蘋果的抽屜的編號,另一個抽屜只用來存儲裝了橘子的抽屜的編號。
定義并初始化一個指針變量,由于運(yùn)算符優(yōu)先級的問題,并沒有固定的定義格式,基本上每種不同的標(biāo)識符都有自己的指針定義格式
int* pVar=&var; //數(shù)據(jù)類型指針變量char (*ptr)[3]={'a','b','c'}; //數(shù)組指針變量,本質(zhì)是指針,指向一個數(shù)組 VS char* str[10]={"this","is","a","string"};指針數(shù)組,本質(zhì)是數(shù)組,每個元素都是一個指針int (*pFcn)(int x)=fcn; //函數(shù)指針變量,指向一個函數(shù)的地址,函數(shù)名就是一個指針
使用指針
int var2=*pVar;//取值int** ppVar=*pVar;//取址,這里定義一個指向指針的指針變量
指針常量VS常量指針
指針常量const int* ptr表示不能通過指針修改指向的變量的內(nèi)容
常量指針int* const ptr表示指針的指向不能改變。
基本數(shù)據(jù)類型char int etc.
基本數(shù)據(jù)類型是C語言規(guī)定好的數(shù)據(jù)類型,它們占據(jù)內(nèi)存的大小,對該塊內(nèi)存的使用方式都是編譯器規(guī)定好的,我們只能使用,不能更改。
在一個典型的32位操作系統(tǒng)中:
數(shù)據(jù)類型占位符長度數(shù)值范圍(指數(shù)表示)數(shù)值范圍(數(shù)字表示)char%c1-2^7~2^7-1-128~127unsigned char%c10~2^8-10~255short%hd2-2^15~2^15-1-32768~32767unsigned short%hu20~2^16-10~65535int%d4-2^31~2^31-1-2147483648~2147483647unsigned int%u40~2^32-10~4294967295long%ld4-2^31~2^31-1-2147483648~2147483647unsigned long%lu40~2^32-10~4294967295float%f或%g4??double%lf或%lg8??
Note:
%f和%lf會保留小數(shù)點(diǎn)后多余的0(就算你寫的5.2,也會輸出5.200000),而%g和%lg不會保留哪些0
不同平臺(eg:32位VS64位系統(tǒng))數(shù)據(jù)類型的長度會有不同,具體需要用sizeof測,上表針對一般32位系統(tǒng),以int為例,一個int占4byte,一個byte占8位,所以一個int由32位二進(jìn)制表示,故int共能表示2^32個數(shù)
float和double的范圍是由指數(shù)的位數(shù)來決定的。float的指數(shù)位有8位,而double的指數(shù)位有11位,分布如下:
float: 1bit(符號位) 8bits(指數(shù)位) 23bits(尾數(shù)位)
double: 1bit(符號位) 11bits(指數(shù)位) 52bits(尾數(shù)位)
So,float的指數(shù)范圍為-127~+128,而double的指數(shù)范圍為-1023~+1024,并且指數(shù)位是按補(bǔ)碼的形式來劃分的。其中負(fù)指數(shù)決定了浮點(diǎn)數(shù)所能表達(dá)的絕對值最小的非零數(shù);而正指數(shù)決定了浮點(diǎn)數(shù)所能表達(dá)的絕對值最大的數(shù),也即決定了浮點(diǎn)數(shù)的取值范圍。
float的范圍為-2^128 ~ +2^128,也即-3.40E+38 ~ +3.40E+38;
double的范圍為-2^1024 ~ +2^1024,也即-1.79E+308 ~ +1.79E+308
有符號的數(shù)據(jù)類型不是分“正數(shù)” 和 “負(fù)數(shù)”,而是 “非負(fù)數(shù)” 和 “負(fù)數(shù)”,其中的區(qū)別在于 0 是非負(fù)數(shù)里的,所以,只需要記住有多少個和有無符號就可以計(jì)算其范圍
基本數(shù)據(jù)類型與指針
int var=10;int* pVar = &var; //定義并聲明一個指向int類型變量的一個指針,并將其指向varint res=*pVar; //對一個指針取值int* pTest=pVar;
字符串
C語言中的字符串用"有效字符"來表示。
C編譯器會自動在有效字符之后再加一個\0(即ASCII的數(shù)字0)表示字符串的結(jié)束,所以一個字符串實(shí)際占用的byte數(shù)目是"有效字符數(shù)+1","Tom"!='T''o''m',前者是字符串,有'\0'結(jié)尾,占4byte,后者不是"字符串",而是"一串字符",沒有'\0'結(jié)尾,占3byte。 有兩種方式測試字符串的長度:sizeof和strlen()
定義一個字符串常量
char* str="this is a string";
定義一個字符串?dāng)?shù)組
char str[]="this is a string";
字符串與指針
當(dāng)我們定義一個字符串常量的時候,C編譯器其實(shí)干了三件事,1.找一塊內(nèi)存,把這個字符串的有效值放進(jìn)去,2.字符串的結(jié)尾加一個'\0',3.把這個字符串的首地址放在標(biāo)識符中。
C語言的字符串有兩種存儲方式,字符串常量和字符串?dāng)?shù)組,二者存儲的內(nèi)容都一樣,也都是一個返回字符串的首地址,區(qū)別是前者是常量,內(nèi)存的內(nèi)容不能修改,后者可以修改。
數(shù)組[]
數(shù)組是在內(nèi)存里一塊區(qū)域里連續(xù)的存儲數(shù)目固定的同一類型數(shù)據(jù),這里的同一類型,既包括基本數(shù)據(jù)類型,也包括復(fù)合數(shù)據(jù)類型,指針等。一塊數(shù)組可以用它的數(shù)組名唯一的表示,這個數(shù)組名其實(shí)就是這塊內(nèi)存的首地址,即第一個元素的首地址。定義數(shù)組時,元素的個數(shù)從1開始算,訪問數(shù)組時,元素的個數(shù)從0開始算。所以數(shù)組名arr是第一個元素arr[0]的地址,arr+1是第二個元素arr[1]的地址,注意,arr+1不是第二個byte的地址,編譯器會以一個元素所占的byte數(shù)為單位進(jìn)行地址的增減。a[i]的實(shí)質(zhì)就是將地址從a開始移動i個單位長度再解引用,即*(a+i)。
定義一個一維數(shù)組
元素類型 數(shù)組名[元素的個數(shù)];
二維(多維)數(shù)組本質(zhì)上還是在一塊連續(xù)的內(nèi)存中存儲數(shù)目確定的同一類型數(shù)據(jù),只不過對這塊數(shù)據(jù)進(jìn)行了"分組",比如,同樣的一塊存儲了1,2,3,4...,9,10的內(nèi)存,用一維數(shù)組表示是int num[10]={1,2,3,4,5,6,7,8,9,10};,而用二維數(shù)組表示是int num[2][5]={1,2,3,4,5,6,7,8,9,10};,內(nèi)存還是那塊內(nèi)存,只不過表達(dá)方式變了,二維數(shù)組相當(dāng)于把這10個數(shù)分成了兩組,每組5個數(shù)
定義一個二維數(shù)組
元素類型 數(shù)組名[組數(shù)][每組元素?cái)?shù)]
定義并初始化一個數(shù)組
char stu1Name[20]="Tom"; //定義并初始化字符數(shù)組,數(shù)組中前4byte被賦值char remark[20]={‘y‘,’e‘,’s‘}; //數(shù)組中前3byte被賦值int vector[]={1,2,3}; //如果數(shù)組元素全部列出,可以省略定義時的元素個數(shù)int vector2[][2]={1,2,3,4}; //如果沒有歧義,二維數(shù)組的第一維可以省略,沒有賦值的部分會被初始化為'0';
指針數(shù)組VS數(shù)組指針
指針數(shù)組的核心詞是"數(shù)組",所以指針數(shù)組表示的是里面的成員都是指針類型的數(shù)組
int* arr[10]; //arr用來存儲10個指向int類型的指針char* strarr[10]; //strarr用來存儲10個指向char類型的指針,因?yàn)樽址膶?shí)質(zhì)就是char*,所以strarr是存儲了10個字符串首地址的數(shù)組
數(shù)組指針的核心詞是"指針",數(shù)組名本身就是一個指針常量,就是第一個元素的地址
int arr[10] = {1,2,34};int* pArr=arr; //將數(shù)組的地址賦值給數(shù)組指針
但是數(shù)組指針多用在二維數(shù)組中,一個int* ptr可以指向int arr[3],但是不能指向二維數(shù)組,二維數(shù)組指針一定要除了元素類型還要至少標(biāo)明數(shù)組的列數(shù),形如int (*ptr)[3],則這個ptr才可以指向任何一個以int為元素類型,列數(shù)為3的數(shù)組,當(dāng)然,也可以同時指定指向數(shù)組的行數(shù)和列數(shù)做進(jìn)一步的限定。
二維數(shù)組指針有行指針和列指針之分
結(jié)構(gòu)體struct
結(jié)構(gòu)體是把不同的數(shù)據(jù)類型進(jìn)行打包的一種數(shù)據(jù)類型,由程序員自己定義。既然說結(jié)構(gòu)體是一種數(shù)據(jù)類型,而一個數(shù)據(jù)類型是沒有值的,所以結(jié)構(gòu)體在定義時不能進(jìn)行賦值。
定義一個有名結(jié)構(gòu)體類型,使用變量列表創(chuàng)建變量,使用初始化列表進(jìn)行初始化
struct StuInfo{ int age; char name[20];}stu1={10,"Tom"},stu2={11,"Rendo"};
定義一個結(jié)構(gòu)體類型,習(xí)慣上將自定義的結(jié)構(gòu)體類型的首字母大寫,以便和變量進(jìn)行區(qū)分
struct StuInfo{ int age; char name[20];};//或typedef struct{ int age; char name[20];}StuInfo2;
定義一個結(jié)構(gòu)體類型的變量并進(jìn)行列表初始化,列表初始化,即只能在初始化時使用,如果定義變量的時候不用,那么之后就只能逐個元素的賦值。
struct StudInfo stu1={10,"Tom"};//或StudInfo2 stu2={11,"Rendo"};
給結(jié)構(gòu)體變量賦值
stu.age=10;stu.name[0]='T';stu.name[1]='o';stu.name[2]='m';stu.name[3]='\0';
結(jié)構(gòu)體與指針
struct StuInfo* pSt; //定義一個指向結(jié)構(gòu)體StuInfo類型的指針struct StuInfo stu; //定義一個結(jié)構(gòu)體StuInfo類型的變量pSt = &stu; //將結(jié)構(gòu)體變量stu的地址賦給pSt
共用體union
共用體的各個成員共享同一塊內(nèi)存,如果各個成員的長度不同,會取最長的那個成員的長度作為共用體的長度
定義一個union
union Data{ int num1; double num2;};//或typedef union{ int num1; double num2;}Data;
創(chuàng)建共用體變量
union Data{ int num1; double num2;};//或typedef union{ int num1; double num2;}Data;
定義一個共用體變量
union Data data1,data2;//或Data data1,data2;
使用共用體
data1.num1=2;data2.num2=3.3;
枚舉enum
顧名思義,枚舉就是一個一個的列舉,枚舉類型用自定義的元素來代替列舉元素的編號,方便記憶,但是其本質(zhì)上還是一個整數(shù)。
定義一個enum類型weekday
enum weekday{sun,mon,tue,wed,thu,fri,sat};
定義了一個weekday類型的變量
enum weekday day;
使用day變量
day=mon;
?
評論