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