




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
C語言知識點復習C語言——只看這一篇就夠了!數據類型?用不同數據類型所定義的變量所占空間大小不一樣,定義的變量不是保存于數據類型中,而是因為只有定義了該數據類型的變量才能保存數據。一、整型?1、整型(int)四字節,默認有符號(-231-231-1),無符號加unsigned(0-232-1)(十位數);?2、短整型(shortint),兩字節(-215-215-1)(五位數);?3、長整型(longint),四字節(同int,在目前的操作系統中幾乎沒有區別);?4、長長整型(longlongint),八字節(-263-263-1),無符號(0-264-1);二、浮點型?1、單精度浮點數(float),四字節,保留小數點后6位?2、雙精度浮點數(double),八字節,保留小數點后15位int為一個32為的存儲單元,longlong為64為的存儲單元1B/byte(字節)=8bit(比特)(位)1KB(千字節)=1024B/byte(字節)1MB=1024KB1GB=1024MB1TB=1024GB1PB=1024TB1EB=1024PB三、字符型?char,用于儲存字符,和int很像,可用ASCII碼來儲存字符,eg:chargrade=’A’;chargrade=65;''單引號為字符,eg:chara='a';?""雙引號為字符串,eg:char*a=“asd”;編譯器會自動給字符串結尾添加’\0‘來作為字符結束標識,strlen函數中不統計\0,但是\0在內存中占據空間。?除此之外,還有轉義字符,通過反斜杠來完成相關操作,如果要特殊字符轉字面字符需要另外添加反斜杠,轉義字符在字符串中占空間,但是只計算一個長度,\0不計長度。?四、變量和常量?作用域(scope),程序設計概念,通常來說,一段程序代碼中所用到的名字并不總是有效/可用的,而限定這個名字的可用性的代碼范圍就是這個名字的作用域。?生命周期:變量的生命周期指的是變量的創建到變量的銷毀之間的一個時間段#include<stdio.h>intglobal=2019;//全局變量intmain({intlocal=2018;//局部變量return0;}。分支及循環語句一、分支語句?1、if語句?語法結構:if(表達式)語句;if(表達式){語句列表1}else{語句列表2;}//多分支if(表達式1){語句列表1;}elseif(表達式2){語句列表2;}else{語句列表3;}。?表達式部分為真則執行語句(0為假,非0為真),盡量在每個分支語句后都加{},否則只會執行分支后第一條語句。?else在沒有括號的情況下遵循就近原則所以在多重if語句嵌套使用情況下一定要加括號!?2、switch語句?switch作為分支結構常用于多分支的情況,可以簡化多重if語句嵌套的情況。?語法結構switch(表達式A){case常量表達式1:語句1;break;case常量表達式2:語句2;break;……case常量表達式n:語句n;break;default:語句n+1;break;}。?其中?1、case后第一句不可定義變量,必須跟常量或者常量表達式,并且不可相同;?2、break在語句中可以起到劃分作用,不可省略,否則無法實現分支功能;?3、default語句不應該省略,一般推薦位語句列表末尾;?4、switch語句結束條件:①遇到break;②執行到語句列表末尾。二、循環語句?1、while語句?語法結構while(表達式){循環語句;}?注:在循環語句中break的作用是停止后期所有循環,continue的作用是終止本次循環,開始下一次循環的判斷。?2、for語句for(表達式1;表達式2;表達式3){循環語句;}?表達式1為初始化部分,用于初始化循環變量,當表達式1為空時直接進入循環;?表達式2為條件判斷部分,用于判斷循環是否終止,當表達式2為空時為死循環;?表達式3為調整部分,用于循環條件的調整。?注:建議使用“前閉后開”來限定區間范圍。for(i=0;i<10;i++){a[i]=i;}?3、dowhile語句do{循環語句;}while(表達式);?循環體至少執行一次,while之后記得加分號。?二分查找函數循環實現范例:intbin_search(intarr[],intleft,intright,intkey){intmid=0;while(left<=right){mid=(left+right)>>1;if(arr[mid]>key){right=mid-1;}elseif(arr[mid]<key){left=mid+1;}else{returnmid;//找到了,返回下標}}return-1;//找不到}。函數一、庫函數?C語言基礎庫中的函數,在添加頭文件后可直接調用。二、自定義函數1、函數組成?由函數名、返回值類型、函數參數以及函數體組成。?實參:真實的傳入函數的變量,**在被調用時會發生臨時拷貝,并非把原來的變量直接放入函數中,**只是把實參的數據拷貝給形參。?形參:函數名括號后的變量,因為形參只有在被調用的時候才被實例化并分配空間(形參實例化),**在被調用過后即被銷毀,只在該函數中有效(局部變量),**所以叫形參。?函數聲明,要滿足先聲明后使用的原則,由返回值類型、函數名與函數參數組成(需要加分號),當我們用到很多函數聲明的時候,為了方便我們的調用,我們可以創建一個頭文件.h(比如test.h),將函數聲明放在頭文件當中,在寫頭文件時,要注意加上#pragmaonce。//函數定義doubleAdd(doublex,doubley){returnx+y;}//函數聲明doubleAdd(doublex,doubley);2、函數調用?函數也可以進行嵌套調用以及鏈式訪問。?嵌套調用樣例:#include<stdio.h>voidnew_line({printf("hehe\n");}voidthree_line({inti=0;for(i=0;i<3;i++){new_line(;}}intmain({three_line(;return0;}。?鏈式訪問樣例:#include<stdio.h>#include<string.h>intmain({chararr[20]="hello";intret=strlen(strcat(arr,"bit"));printf("%d\n",ret);return0;}。3、函數遞歸?程序自身調用被稱為遞歸,把復雜問題層層轉化為與原問題類似的小問題,函數在調用自身的情況下存在不合法遞歸(即無限次的遞歸導致棧溢出)。?所以在使用遞歸的時候一定要有遞歸出口,否則會陷入死循環導致棧溢出!?**注:**棧結構為電腦存儲的一部分,從高地址處向下開辟存儲空間,與用于開辟動態存儲空間的堆相向開辟(堆為從低地址出向上開辟存儲空間),而函數調用將會形成棧幀,函數返回后自動釋放棧幀結構,在此過程中,該函數定義的所有局部變量都在該函數的棧幀內進行空間開辟。樣例:求n的階乘intfactorial(intn){if(n<=1)return1;elsereturnn*factorial(n-1);}?遞歸與迭代?遞歸在使用過程中由于頻繁進行函數調用,且每次調用都需要時間成本以及空間成本,所以遞歸程序簡單,但是可能導致遞歸效率變低的問題,而迭代方案通過對變量值進行替換所以不會造成棧溢出,解決了效率低下的問題。?樣例(求斐波那契數列第n個的值)://遞歸實現intfibrec(intn){if(n<=2)retuen1;elsereturnfibrec(n-1)+fibrec(n-2);}//迭代實現intfibite(intn){intfir=1,sec=1,thd=2;if(n<=2)return1;else{while(n>2){fir=sec;sec=thd;thd=fir+sec;n--;}returnthd;}}。數組一、一維數組的創建與初始化?創建數組時數組空間為整體開辟整體釋放,在內存中是連續存放,在定義時就已經確定數組大小(下標不可為0),且不可被整體賦值。在數組的創建過程中,如果進行了初始化則可不指定數組的大小,多維數組按照一維數組進行理解。?數組傳參發生降維,降維成指向其(數組)內部元素類型的指針。?數組名一般情況下都指的是首元素的地址,但如果sizeof(單獨出現以及&后跟數組名時表示的是整個數組ints[5];//表示數組首元素地址printf("%d\n",sizeof(s+1));//結果為4/8,指針的具體大小根據編譯器的不同大小不同//表示整個數組printf("%d\n",sizeof(s));//結果為20。二、數組傳參(函數)?由于在傳參過程中如果拷貝整個指針會導致效率大大降低甚至導致棧溢出,所以數組傳參要發降維問題,函數內數組作為參數時,實參為首元素地址,形參為指針。?在訪問結構體成員時也同樣要發生類似的操作,用指向結構體的指針來指代結構體。typedefstructnode{inta;intb;}point;voidpop(int*p){}intmain({pointa;int*p=a;pop(p);return0;}。?傳參樣例://用數組的形式傳遞參數,不需要指定參數的大小,傳的只是數組首元素的地址。voidtest(intarr[]){}//也可以傳入數組大小voidtest(intarr[10]){}//數組降維,用指針進行接收,傳的是數組首元素的地址voidtest(int*arr){}//二維數組傳參,第一個方括號可以空,但是第二個不可以空voidtest(intarr[][5]){}voidtest(intarr[4][5]){}//傳過去的是二維數組的數組名,即數組首元素的地址,也就是第一行的地址,第一行也是個數組,用一個數組指針接收(比較少用)voidtest(int(*arr)[5]){}。三、字符數組chara[]={'a','x','d'};//此處由于結尾沒有'\0',strlen的機制是遇到'\0'即停止,所以在結尾沒有'\0'時為隨機數//strlen(a)為隨機數//sizeof(a)為3chara[]={'a','x','d','\0'};//strlen(a)為3//sizeof(a)為4char*a="axd";//或chara[]="axd"http://直接通過""定義字符串時,會自動在結尾補'\0',不需要自行補充,但'\0'依舊會占據一個字節//strlen(a)為3//sizeof(a)為4charc[5]={'a','b','\0','c','\0'};printf("%s",c);//結果為ab,因為字符串結束標志位'\0'。操作符一、運算優先級?注:①++/–高于解引用;?②解引用高于±*/?③±*/高于位運算;?④位運算高于+=、-=、/=、*=;%操作兩邊必須是整數。二、二進制中的操作符1、位運算基本介紹與運算:&?同1則1,否則為0;或運算:|?同0為0,否則為1非運算:~?1取00取1異或運算:^?兩者相等為0,不等為1移位運算操作符:<<左移;>>右移?①**<<左移:**左邊拋棄末尾補0;負數對反碼的補碼進行移位操作;相當于乘2;?②**>>右移:有符號的補符號位**,無符號的補0;相當于除以2。2、反碼與補碼?**反碼:**正數的反碼為原碼本身,負數反碼符號位不變,剩余的數字位取反;?**補碼:**正數的補碼為原碼本身,負數的補碼為反碼+1。三、隱式類型轉換?隱式類型轉換的原因:參與計算的數據如果類型不同無法直接進行計算。?整型提升:有符號的補符號位,無符號的補0(符號位為最外面的那位)?樣例:?例題,求循環次數?解答:?unsignedchar8位數據位,范圍在0-255,所以-2(11111110)時,變成254;同理-1(11111111)時,變成255;最后減到0時,不滿足循環條件,for停止。剛好173次。(741==>共(7-1)/3+1=3次,1-3=-2,即254,繼續循環)254251…52==>共(254-2)/3+1=85次(2-3=-1,即255,繼續循環)255252…63==>共(255-5)/3+1=85次(3-3=0,退出循環)所以總共173次。指針?指針變量是個變量,指針本身是個地址,用于存放內存單元的地址。?指針時用來存放地址的,指針類型的變量無論指向目標是什么類型,指針本身在32位平臺所占大小都為4個字節,在64位平臺是8個字節。#include<stdio.h>intmain({inta=10;//在內存中開辟一塊空間,左值為空間,右值為內容int*p=&a;//type*p//這里我們對變量a,取出它的地址,可以使用&操作符。//將a的地址存放在p變量中,p就是一個之指針變量。return0;}。一、指針的解引用?1、對指針的解引用只能看到sizeof(type)個字節的數據;?2、按字節為單位,數據有高權值和低權值之分,地址有低地址和高地址之分;?3、數據低權值位在低地址處即為小端存儲,反之則為大端存儲。(“小小小”)二、野指針概念?指向的位置是不可知的指針。規避?1、指針在定義時就進行初始化;?2、避免指針越界(eg:注意循環時循環次數的限制);?3、指針使用完即進行指針指向空間釋放;?4、避免返回局部變量的地址;?5、指針使用前檢查其有效性。三、指針運算?1、指針±整數,等價于±sizeof(type);?2、指針-指針,兩指針必須同一類型,一般用于數組與字符串求其兩地址間相隔的單元格數,否則無效(指針+指針為非法操作);?3、指針的關系運算。?4、指針和數組都可以用中括號或者解引用(二者互通)。四、字符指針1、字符指針在指針的類型中我們知道有一種指針類型為字符指針char*;一般使用方法intmain({charch='w';char*pc=&ch;*pc='w';return0;}用char*指針指向字符串intmain({constchar*pstr="hellobit.";printf("%s\n",pstr);return0;}//上述代碼中把字符串hellobit.的首地址放入了指針中。需注意字符串可以以字符數組的形式給出,但是此時的字符數組附有存儲功能,而字符指針具有常量屬性,指向的是常量區的內容,因此不可被修改,可以寫作:constchar*str="helloworld";//從上圖表示不可被修改?也正因為這個原因C/C++會把常量字符串存儲到單獨的一個內存區域,當幾個指針指向同一個字符串的時候,他們實際會指向同一塊內存。但是用相同的常量字符串去初始化不同的數組的時候就會開辟出不同的內存塊。#include<stdio.h>intmain({charstr1[]="helloworld.";charstr2[]="helloworld.";constchar*str3="helloworld.";constchar*str4="helloworld.";if(str1==str2)printf("str1andstr2aresame\n");elseprintf("str1andstr2arenotsame\n");if(str3==str4)printf("str3andstr4aresame\n");elseprintf("str3andstr4arenotsame\n");return0;}。2、const知識點?在此說一下const的一些知識點:?①const修飾的變量不能被直接修改,但是可以通過指針在進行類型強轉來修改(只是可以但是完全沒必要);?②const修飾指針,表示不可以通過指針來修改所指目標;?③const能用則用,會很好的保護數據。?const的作用:?①寫給編譯器看,提前發現可能錯誤的修改;?②寫給程序員看,提示該變量不建議修改。constint*p=&a;*p=20;//錯誤,*p所指的值不可以修改p=&n;//正確,*p的指向可以修改int*constq=&m;*q=20;//正確,此時const修飾的是q,此時q所指向的值可以進行修改q=&t;//錯誤,由于const修飾的是q,此時的q的指向不可以進行修改constinta=10;//若consta=10,編譯器也會默認為a是int類型的int*P=(int*)&a;//注意需要強制&a前需要加int*類型強制類型轉換(&a的原本類型為constint*)*P=12;。五、指針數組指針數組本質上是數組,該類數組內存放的的元素是指針。int*arr1[10];//整形指針的數組char*arr2[4];//一級字符指針的數組char**arr3[5];//二級字符指針的數組六、數組指針1、數組指針定義指針數組本質上是指針,該類指針指向的是一個數組。example:int(*p)[10];//解釋:p先和*結合,說明p是一個指針變量,然后指著指向的是一個大小為10個整型的數組。所以p是一個指針,指向一個數組,叫數組指針2、數組指針&數組首先需要看的是數組名與&數組名(可以等價于數組指針)之間的關系#include<stdio.h>intmain({intarr[10]={0};printf("arr=%p\n",arr);printf("&arr=%p\n",&arr);printf("arr+1=%p\n",arr+1);printf("&arr+1=%p\n",&arr+1);return0;}。根據上面的代碼我們發現,其實&arr和arr,雖然值是一樣的,但是意義應該不一樣的。實際上:&arr表示的是數組的地址,而不是數組首元素的地址。(細細體會一下)本例中&arr的類型是:int(*)[10],是一種數組指針類型數組的地址+1,跳過整個數組的大小,所以&arr+1相對于&arr的差值是40。七、數組傳參,指針傳參1、一維數組傳參數組傳參會發生降維,最終傳入的是首元素的地址(指針),并利用此來訪問數組內其他元素。#include<stdio.h>voidtest(intarr[])//ok{}voidtest(intarr[10])//ok{}voidtest(int*arr)//ok{}voidtest2(int*arr[20])//不ok{}voidtest2(int**arr)//不ok{}intmain({intarr[10]={0};int*arr2[20]={0};test(arr);test2(arr2);}。2、二維數組傳參二維數組傳參,函數形參的設計只能省略第一個[]的數字。因為對一個二維數組,可以不知道有多少行,但是必須知道一行多少元素。voidtest(intarr[3][5])//ok{}voidtest(intarr[][])//不ok{}voidtest(intarr[][5])//ok{}voidtest(int*arr)//不ok{}voidtest(int(*arr)[5])//ok{}voidtest(int*arr[5])//不ok{}voidtest(int**arr)//ok{}intmain({intarr[3][5]={0};test(arr);}。3、一級指針傳參需要傳入一個地址#include<stdio.h>voidprint(int*p,intsize){inti=0;for(i=0;i<size;i++){printf("%d\n",*(p+i));}}intmain({intarr[10]={1,2,3,4,5,6,7,8,9};int*p=arr;intsize=sizeof(arr)/sizeof(arr[0]);//一級指針p,傳給函數print(p,size);return0;}。4、二級指針傳參#include<stdio.h>voidtest(int**ptr){printf("num=%d\n",**ptr);}intmain({intn=10;int*p=&n;int**pp=&p;test(pp);test(&p);return0;}。八、函數指針1、函數指針定義?函數指針是指指向函數而非指向對象的指針。像其他指針一樣,函數指針也指向某個特定的類型(特定的函數類型)。函數類型由其返回類型以及形參表確定,而與函數名無關。?代碼在電腦中同樣占據內存空間,所以具有存儲地址,而代碼部分在電腦中也是不可被修改的類似字符串常量。?在函數中,函數名單獨時即為函數的地址(eg:main=&main),所以在用指針調用函數時,可以直接用指針調用不需要加*Type(*pFunc)(datatypeargs);//pFunc為函數指針,Type為數據類型,參數(datatypeargs)可以有多個,也可以沒有。使用示例boolmax(inta,intb){if(a>b){returna;}else{returnb;}}voidTest({bool(*pFunc)(int,double);pFunc=max;cout<<max(5,10)<<endl;}。九、函數指針數組指針指向一個數組,數組的元素都是函數指針使用方法:把幾個相同類型的函數地址放到一個數組中,這個數組就是函數指針的數組。十、回調函數解釋:調用庫中函數,但是庫中函數需要編寫程序時編寫一個調用函數,該庫中的函數為回調函數。也就是說一個通過函數指針調用的函數。如果你把函數的指針(地址)作為參數傳遞給另一個函數,當這個指針被用來調用其所指向的函數時,我們就說這是回調函數。?回調函數必須在中間函數以及回調函數同時具備時才可以實現。回調函數就是回調函數不是由該函數的實現方直接調用,而是在特定的事件或條件發生時由另外的一方調用的,用于對該事件或條件進行響應。結構體1、基本定義?**注:**①結構體不可以自引用!但可以在結構體內定義該結構體類型的指針!?②定義結構體本質是新增一種類型;?③結構體傳參要傳結構體地址(指針),以此提高效率。structnode1{inta;intb;};typedefstructnode2{intc;intd;}node2;//通過typedef為結構體變量定義一個別名node2,在以后使用中可以使用別名以此提高編寫效率intmain({structnode1s;//用結構體定義變量node2q;//用別名定義變量}。?**注:**結構體不可以自引用!但可以在結構體內定義該結構體類型的指針!structNode{intdata;structNodenext;};//錯誤structNode{intdata;structNode*next;};//正確typedefstructNode{intdata;structNode*next;}Node;//正確。2、結構體變量的定義和初始化structPoint1{intx;inty;}p1;//聲明類型的同時定義變量p1structPointp2;//定義結構體變量p2typedefstructPoint2{intx;inty;}p;pp1;pp2;。在定義結構體變量時,可以在初始化的部分定義其內容,也可以在之后定義。typedefstructPoint2{intx;inty;}p;pp1;p1.x=1;p1.y=2;//可以直接用結構體類型的變量進行定義typedefstructPoint2{intx;inty;}p;p*p2=(p*)malloc(sizeof(p));p2->x=1;p2->y=2;//定義一個指向結構體的指針并為其分配空間即可進行定義。3、結構體的內存對齊(結構體的占用大小的計算)結構體內存空間占用的大小并不是單純的元素相加,而是通過浪費一定量的空間來換取目標數據讀取速度的加快計算方式:①第一個成員在與結構體變量偏移量為0的地址處。②其他成員變量要對齊到某個數字(對齊數)的整數倍的地址處。?(起始偏移量要能整除該成員的對齊數)對齊數=編譯器默認的一個對齊數與該成員大小的較小值。?VS中默認的值為8③結構體總大小為最大對齊數(每個成員變量都有一個對齊數)的整數倍。④如果嵌套了結構體的情況,嵌套的結構體對齊到自己的最大對齊數的整數倍處(即結構體大小),結構體的整體大小就是所有最大對齊數(含嵌套結構體的對齊數)的整數倍。樣例:structS1{chara;intb;charC;};printf("%d\n",sizeof(structS1));char為1個字節,int為4個字節;chara從0偏移開始,占用一個字節;偏移量為1,接下來存放intb,偏移量1不是對齊數4的整數倍,所以向后繼續偏移一直到4,4是對齊數4的整數倍,所以將intb存放在偏移地址為4處,占用4個字節;偏移量變為8,存放charc,占一個字節,偏移量9不是最大對齊數4的整數倍,所以向后繼續偏移直到偏移處為12的地方。圖示如下:自主設置默認對齊數#pragmapack(a)//通過該指令可設置默認對齊數為a位斷位段的聲明和結構是類似的,有兩個不同:1.位段的成員必須是int、unsignedint、signedint或者char(同屬于整型家族);2.位段的成員名后邊有一個冒號和一個數字。structA{int_a:2;int_b:5;int_c:10;int_d:30;};注:①位段的成員可以是intunsignedintsignedint或者是char(屬于整形家族)類型;②位段的空間上是按照需要以4個字節(int)或者1個字節(char)的方式來開辟的;③位段涉及很多不確定因素,位段是不跨平臺的,注重可移植的程序應該避免使用位段;④位斷不需要考慮內存對齊問題所以較為節省空間。總而言之,跟結構相比,位段可以達到同樣的效果,但是可以很好的節省空間,但是有跨平臺的問題存在。枚舉即一一列舉enumDay//星期{Mon,Tues,Wed,Thur,Fri,Sat,Sun//最后一個不加逗號};en
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- DB31/T 1047-2017家政服務溯源管理規范
- DB31/ 749-2013大型游樂設施維修保養規則
- 信息技術在企業管理中的應用考核試卷
- 貨運火車站物流企業市場營銷策劃考核試卷
- 智能交通數據保密及智能管控協議
- 測試團隊溝通方法試題及答案
- 跨國展覽安全責任保證協議
- 跨區域購物中心商鋪租賃權承繼與合同續簽協議
- 跨界合作網絡文學IP影視改編合同
- 知識產權法律審查補充協議
- 診所應急知識培訓課件
- 央行MPA考核細則
- 2025-2030全球及中國自動入侵與攻擊模擬行業市場現狀供需分析及市場深度研究發展前景及規劃可行性分析研究報告
- 大數據時代統計信息安全挑戰與應對策略研究
- 2025年攪拌車市場規模分析
- 高處作業風險及隱患排查(安全檢查)清單
- 網絡與信息安全突發事件應急預案演練記錄
- 超星爾雅學習通《生態文明-撐起美麗中國夢(福建農林大學)》2025章節測試附答案
- 中建安全輪崗
- 《昆蟲記》中考試題及典型模擬題訓練(原卷版)
- 上海市河道水生生物管理維護手冊
評論
0/150
提交評論