C/C++ 常見試題. Pointer

文章推薦指數: 80 %
投票人數:10人

你所不知道的C語言:指標篇 ... C/C++ — 常見C 語言觀念題目總整理(適合考試和面試) ... 指標考題 char s[]="0113256"; char *p=s; printf("%c",*p++); GetunlimitedaccessOpeninappHomeNotificationsListsStoriesWriteC/C++常見試題PointerCallbyValue,CallbyAddress,CallbyReference(C++獨有)http://wp.mlab.tw/?p=176你所不知道的C語言:指標篇https://hackmd.io/@sysprog/HyBPr9WGl?type=view放在函數裡的指標,若是沒有以*p去做處理,而是以p直接去寫入的話,會因為進入函數另外指向的指標而失效,因此要以指標的指標來做處理。

C/C++—常見C語言觀念題目總整理(適合考試和面試)https://mropengate.blogspot.com/2017/08/cc-c.htmlinta;//一個整型數int*a;//一個指向整數的指標int**a;//一個指向指標的指標,它指向的指標是指向一個整型數inta[10];//一個有10個整數型的陣列int*a[10];//一個有10個指標的陣列,該指標是指向一個整數型的int(*a)[10];//一個指向有10個整數型陣列的指標int(*a)(int);//一個指向函數的指標,該函數有一個整數型參數並返回一個整數int(*a[10])(int);//一個有10個指標的陣列,該指標指向一個函數,該函數有一個整數型參數並返回一個整數//秘訣是由後往前念Compare印出1intB=2;voidfunc(int*p){p=&B;}intmain(){intA=1,C=3;int*ptrA=&A;func(ptrA);printf("%d\n",*ptrA);return0;}Compare印出2intB=2;voidfunc(int**p){*p=&B;}intmain(){intA=1,C=3;int*ptrA=&A;func(&ptrA);printf("%d\n",*ptrA);return0;}Explainthisdeclairation.void**(*d)(int&,char**(*)(char*,char**));--------------------------------------------------------------------+disapointertoafunctionthattakestwoparameters:+areferencetoanintand+apointertoafunctionthattakestwoparameters:+apointertoacharand+apointertoapointertoachar+andreturnsapointertoapointertoachar+andreturnsapointertoapointertovoid[C]透過函式記憶體配置—malloc()mallocinanotherfunctionhttp://lee.logdown.com/posts/98518/c-through-the-function-malloc-memory-configuration#include#includevoidgetMemory(char**s){*s=(char*)malloc(sizeof(char));printf("s=%p\n",s);printf("*s=%p\n",*s);}intmain(){char*ch=NULL;getMemory(&ch);printf("&ch=%p\n",&ch);printf("ch=%p\n",ch);return0;}```````````````````````````````````````s=0x7fff5d2ebc00*s=0x7f943bc000e0&ch=0x7fff5d2ebc00ch=0x7f943bc000e0字串String反轉voidswap(char*a,char*b){if(a==b)return;*a^=*b;*b^=*a;*a^=*b;}voidreverseString(char*s,intsSize){inti=0,j=sSize-1;while(i//function宣告intdoAdd(int,int);intdoMinus(int,int);intmain(void){//宣告functionpointer//注意所設定的參數數量與型態int(*my_func_ptr)(int,int);//functionpointer指向doAddmy_func_ptr=doAdd;printf("fp指向doAdd=>%d\n",(*my_func_ptr)(5,3));//結果:8//functionpointer指向doMinusmy_func_ptr=doMinus;printf("fp指向doMinus=>%d\n",(*my_func_ptr)(5,3));//結果:2return0;}//endmainintdoAdd(inta,intb){returna+b;}//enddoAddintdoMinus(inta,intb){returna-b;}//enddoMinus結合typedef結合typedeftypedefint(*MathMethod)(int,int);意即把int(*)(int,int)簡化成MathMethod--------------------------------------------------------------------typedefint(*MathMethod)(int,int);intMul(inta,intb){returna*b;}intDivide(inta,intb){returna/b;}intMinus(inta,intb){returna-b;}intAdd(inta,intb){returna+b;}intCalc(intx,inty,MathMethodOpt){returnOpt(x,y);}intmain(){inta=8,b=7;printf("axb=%d\n",Calc(a,b,Mul));printf("a/b=%d\n",Calc(a,b,Divide));printf("a+b=%d\n",Calc(a,b,Add));printf("a-b=%d\n",Calc(a,b,Minus));}sizeofsizeof不是函式,不會在執行時計算變數或型別的值,而是在編譯時,所有的sizeof都被具體的值替換。

doublef(){printf("ComeintoDoublef...\n");return0.0;}intmain(){intvar=0;intsize=sizeof(var++);//sizeof(var++)在編譯時會直接被替換++不會執行printf("var=%d,size=%d\n",var,size);size=sizeof(f());printf("size=%d\n",size);return0;}##outputvar=0,size=4size=8常見考題64bitsizeof(string)=8sizeof(char)=1sizeof(p)=8sizeof(short)=2sizeof(int)=4sizeof(long)=8sizeof(longlong)=8sizeof(size_t)=8sizeof(double)=8sizeof(longdouble)=1632bitsizeof(string)=4sizeof(char)=1sizeof(p)=4//指標sizeof(short)=2sizeof(int)=4//怕因環境影響程式,絕大多數64,32的編譯器是一樣大sizeof(long)=4sizeof(longlong)=8sizeof(size_t)=4sizeof(double)=8sizeof(longdouble)=12//看作long+double=4+8=12Explain“struct”“union”“enum”structEmployee{ charname[30];//名字 intage;//年齡 chargender;//性別,'M'or'F' doublesalary;//薪水};structEmployeeemployee;//宣告變數employee,記得前面要加structunionVar{ charch; intnum1; doublenum2;};除非特別指定,不然都是由0開始,接下來遞增1,例如以下語法:enumweek{Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday};以上從Sunday開始,各個識別字被依序設定為0到6,你也可以指定數值enumweek{Monday=1,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday};malloc,calloc,memset,realloc[link]int*dynArr;intarrLen=10;//配置未初始化的記憶體空間dynArr=malloc(arrLen*sizeof(int));//dynArr=calloc(1000,sizeof(int));if(dynArr==NULL){fprintf(stderr,"Error:unabletoallocaterequiredmemory\n");return1;}//將記憶體初始化為0memset(dynArr,0,arrLen*sizeof(int));int*dynArr2=realloc(dynArr,sizeof(int)*arrLen*2);//若記憶體空間大小是足夠的話,有機會讓dynArr2跟dynArr的記憶體位置相同//不過如果dynArr後面已經沒空間的話,realloc會另外找新的空間給dynArr2,這時候位置可能就會不同。

volatile以上的i,j,k很有可能被compiler最佳化而導致產生i=j=k=*pPort;的code,也就是說只從pPort讀取一次,而產生i=j=k的結果,但是原本的程式的目的是要從同一個I/Oport讀取3次的值給不同的變數,i,j,k的值很可能不同(例如從此I/Oport讀取溫度),因此i=j=k的結果不是我們所要的一個參數可以同時是const也是volatile嗎?解釋為什麼。

∙是的。

舉的例子是"只讀的狀態暫存器"。

它是volatile因為它可能被意想不到地改變。

它是const因為程式不應該試圖去修改它。

lvaluevsrvalue[link]左值讓一段expression成為一個有名稱的物件;而右值只是一段expression的結果且隨時會蒸發不見。

所以像++x是左值而x++卻是右值。

可以利用一個簡單的方法來check一段expression是lvalue或rvalue,就是看看可不可以使用&運算元對該expression取得他的位置。

左值和右值皆可以為non-const和const(用non-const似乎較modifiable來的直覺),以下為範例:stringone("cute");conststringtwo("fluffy");stringthree(){return"kittens";}conststringfour(){return"areanessentialpartofahealthydiet";}one;//modifiablelvaluetwo;//constlvaluethree();//modifiablervaluefour();//constrvalue[以下待整理]Lvalue:就是一個運算式後還保留其狀態的一個物件就是Lvalue;也就是說所有的變數(variables)包含nonmodifiable,const的變數都是Lvalue.這邊一個重點是const的變數也是LvalueRvalue:就是一個運算式過後其狀態就不會被保留了,也就是一個暫存的數值另一種說法(非完全正確,但是可以依此來稍做判斷)能出現在assignment運算子(=)的左邊的稱為Lvalue,而只能出現在右邊的稱為Rvalue這邊只有說出現在左邊的是Lvalue,但沒說Lvalue不能出現在右邊,因此Lvalue在=運算子的左右兩邊都是被允許的,而Rvalue是不能出現在左邊的;這邊有沒有注意到,Lvalue是可以被放到右邊的,也就是說Lvalue也可以被當作Rvalue,但是Rvalue就不能被當作是Lvaluestatic當變數有宣告時加上static限定時,一但變數生成,它就會一直存在記憶體之中,即使函式執行完畢,變數也不會消失。

在一個原始程式文件中宣告全域static變數,還表示其可以存取的範圍僅限於該原始程式文件之中,也可以將函式宣告為static。

(C++)若是在class的function前呼叫,則可以在不初始instance的情況下呼叫函數。

C語言static有兩個目的staticstorage(靜態存儲):變數儲存空間為staticstorage而非functionstack,使變數生命週期與程式相同。

internallinkage(內部連結):限制變數可視範圍於檔案內。

(聽說這是後來加的,為了減少保留字的使用所以也用static)function使用static修飾一個static函式表示,其可以呼叫的範圍限於該原始碼文件之中,如果有些函式僅想在該原始程式文件之中使用,則可以宣告為static,這也可以避免與其他人寫的函式名稱衝突的問題。

記憶體配置[link]global:用來放全域變數、靜態變數(static)等等。

stack:台灣正體中文稱為堆疊,大陸叫做棧。

區域變數、函式的參數與函式的位址等等,由系統管理,必須在編譯時期為已知。

這些變數的回收會發生在它從堆疊pop出去的時候,因為個數、大小什麼的都是已知,所以系統知道怎麼進行配置與回收。

heap:台灣正體中文稱為堆積,大陸叫做堆。

這裡的記憶體由使用者負責進行回收,配置則是由malloc或是new來負責。

使用這裡的記憶體主要是用在編譯時期還不知道大小或個數的變數。

例如說,你需要用一個陣列,這個陣列的大小要在執行的時候由使用者的輸入來決定,那你就只能使用動態配置,也就是把這個陣列配置在heap中。

.bsssection[link_1]1.當globalvariable未被初始化時;2.或是globalvariable被初始化成零時。

如果(但是確實有這種應用場合)我們不想讓variable被放到.bsssection呢?做法有二:1.「傳統做法」,程式設計師只要將globalvariable初始化為「非零」值即可。

2.利用gcc-fno-zero-initialized-in-bss如:gcc-fno-zero-initialized-in-bss-O2-obssbss.cQuickSortCLanguagevoidquickSort(int*nums,inthead,inttail){if(head>=tail){return;}intcomp=nums[head];inti=head,j=tail;while(i=comp&&i&nums,intstart,intend){if(start>=end)return;intleft=start+1,right=end;while(leftnums[start])right--;elsestd::swap(nums[left],nums[right--]);}if(nums[left]>nums[start])left--;std:swap(nums[left],nums[start]);quickSort(nums,left+1,end);quickSort(nums,start,left-1);}typedeftypedef保留字可以為資料型態建立別名,使程式更易閱讀理解。

typedefstructstructNameee{charname[16];intage;structstructNameee*ptr;}PERSON;intmain(void){PERSONperson1={"Amy",20};person1.age=21;}綜合考題Q1.請試著寫出下面代碼的輸出:#include#includeintmain(){charstrAry[]=“Thisisstring”;char*aryPtr=strAry;int*intPtr=(int*)strAry;printf(“\t[Line01]strAry=%s\n”,strAry);//Thisisstringprintf(“\t[Line02]aryPtr=%s\n”,aryPtr);//Thisisstring//printf(“\t[LineX]*aryPtr=%s\n”,*aryPtr);//Segmentfaultprintf(“\t[Line03]sizeof(aryPtr)=%d\n”,sizeof(aryPtr));//4printf(“\t[Line04]sizeof(*aryPtr)=%d\n”,sizeof(*aryPtr));//1printf(“\t[Line05]*aryPtr=’%c’\n”,*aryPtr);//'T'printf(“\t[Line06]*aryPtr+1=’%c’\n”,*aryPtr+1);//'U'printf(“\t[Line07]*(aryPtr+1)=’%c’\n”,*(aryPtr+1));//'h'printf(“\t[Line08]sizeof(intPtr)=%d\n”,sizeof(intPtr));//4printf(“\t[Line09]sizeof(*intPtr)=%d\n”,sizeof(*intPtr));//4printf(“\t[Line10]intPtr=%s\n”,intPtr);//Thisisstring//printf(“\t[LineX]*intPtr=%s\n”,*intPtr);//Segmentfaultprintf(“\t[Line11]*intPtr=’%c’\n”,*intPtr);//'T'printf(“\t[Line12]*intPtr+1=’%c’\n”,*intPtr+1);//'U'printf(“\t[Line13]*(intPtr+1)=’%c’\n”,*(intPtr+1));//''return0;}Ans.[Line01]strAry=Thisisstring#字串陣列char[]=”…”會自動加上NULL到結尾.[Line02]aryPtr=Thisisstring#同上,只是把aryPtr指標指向strAry的位置.strAry本身也是個指標.[Line03]sizeof(aryPtr)=4#指標的大小根據系統是32bit(4byte)或是64bit(8bypte)有所不同.[Line04]sizeof(*aryPtr)=1#char的大小為1byte.[Line05]*aryPtr=’T’#指向字串中第一個字元‘T’[Line06]*aryPtr+1=’U’#char‘T’+1=char‘U’.->ASCII‘T’=84.84+1=85=ASCII‘U’.[Line07]*(aryPtr+1)=’h’#將aryPtr指標移動一個char的位置(1個byte的距離),即是字串的第二個字元‘h’.[Line08]sizeof(intPtr)=4#同Line03[Line09]sizeof(*intPtr)=4#int類型的大小為4byte.[Line10]intPtr=Thisisstring#雖然用int*指定pointer類型,但是在printf使用‘%s’,故還是打印出字串出來.[Line11]*intPtr=’T’#指向字串中第一個字元‘T’.[Line12]*intPtr+1=’U’#同Line6[Line13]*(intPtr+1)=’‘#因為指標類型為int,故移動一個位置為4byte,所以指向第0+4=4位置上的字元,即字串的第五個字元(從0開始).Q2.輸出為何for(unsignedinti=10;i>=0;--i){cout<0113234->0123456Q4.陣列指標考題intmain(){inta[]={1,2,3,4,5,6,7,9};int*ptr=(int*)(&a+1);printf("%d\n",&a);printf("%d\n",&a+1);printf("%d\n",ptr);printf("%d\n",*(ptr));printf("%d\n",ptr-1);printf("%d\n",*(ptr-1));printf("%d\n",ptr-2);printf("%d\n",*(ptr-2));printf("%d\n",*a);printf("%d\n",*a+7);printf("%d\n",*(a+7));}Ans.intmain(){inta[]={1,2,3,4,5,6,7,9};int*ptr=(int*)(&a+1);printf("%d\n",&a);//26410768printf("%d\n",&a+1);//26410800若以&a後面接+1會直接多個長度printf("%d\n",ptr);//26410800printf("%d\n",*(ptr));//0->theonenexttoa[]printf("%d\n",ptr-1);//26410796printf("%d\n",*(ptr-1));//9->a[8-1]printf("%d\n",ptr-2);//26410792printf("%d\n",*(ptr-2));//7->a[8-2]printf("%d\n",*a);//1->a[0]printf("%d\n",*a+7);//8->a[0]+7printf("%d\n",*(a+7));//9->a[0+7]}Q5.陣列指標型態考題intarr[]={10,20,30,40,50};int*ptr1=arr;int*ptr2=arr+5;printf("%d\n",(ptr2-ptr1));//5printf("%d\n",(char*)ptr2-(char*)ptr1);//20Q6.多重陣列考題char*str[][2]={"professor","Justin","teacher","Momor","student","Caterpillar"};charstr2[3][10]={"professor","Justin","etc"};printf("%s\n",str[1][1]);//Momorprintf("%c\n",str2[1][1]);//uQ6–1.多重陣列考題intmain(){doubledata[3][5]={{1,3,4,5,10},{7,8,9,10,11},{2,12,6,15,14}};cout<0x00000111v=v1|v2;//v=0x00001313程式實作:Q1.在一個數值中計算幾個bit為1while(x){x&=(x-1);cnt++;}Q2.將一個數值的奇偶bit互換x=(x&0xaaaaaaaa)>>1|(x&0x55555555)<<1;Q3.將一個字串reversevoidswap(char*a,char*b){if(a==b)return;*a^=*b;*b^=*a;*a^=*b;}voidreverseString(char*s,intsSize){inti=0,j=sSize-1;while(ival=x;tmp->next=NULL;//forinitializeif(NULL==*head){*head=tmp;return;}//dummyforinserteasilystructNode*dummy=(structNode*)malloc(sizeof(structNode));dummy->val=0;dummy->next=*head;//variablefastfortraversalstructNode*fast=dummy;while(NULL!=fast&&NULL!=fast->next){if(x>fast->next->val){fast=fast->next;}else{tmp->next=fast->next;fast->next=tmp;*head=dummy->next;return;}}//ifxisthemaximumvaluefast->next=tmp;return;}DeletetionstructNode{intval;structNode*next;}voiddelete(structNode**head,intx){//dummyforinserteasilystructNode*dummy=(structNode*)malloc(sizeof(structNode));dummy->val=0;dummy->next=*head;//variablefastfortraversalstructNode*fast=dummy;while(NULL!=fast&&NULL!=fast->next){if(x==fast->next->val){fast=fast->next;structNode*tmp=fast->next;fast->next-fast->next->next;free(tmp);}}return;}Q6.QuickSortvoidquickSort(int*nums,inthead,inttail){if(head>=tail){return;}intcomp=nums[head];inti=head,j=tail;while(i=comp&&i=numsSize){returnnums;}int*tobe=(int*)malloc(numsSize*sizeof(int));memcpy(tobe,nums,numsSize*sizeof(int));quickSort(tobe,0,numsSize-1);returntobe;}Q7.MergeSortvoidMerge(std::vector&Array,intfront,intmid,intend){//利用std::vector的constructor,//把array[front]~array[mid]放進LeftSub[]//把array[mid+1]~array[end]放進RightSub[]std::vectorLeftSub(Array.begin()+front,Array.begin()+mid+1),RightSub(Array.begin()+mid+1,Array.begin()+end+1);LeftSub.insert(LeftSub.end(),Max);//在LeftSub[]尾端加入值為Max的元素RightSub.insert(RightSub.end(),Max);//在RightSub[]尾端加入值為Max的元素intidxLeft=0,idxRight=0;for(inti=front;i<=end;i++){if(LeftSub[idxLeft]<=RightSub[idxRight]){Array[i]=LeftSub[idxLeft];idxLeft++;}else{Array[i]=RightSub[idxRight];idxRight++;}}}voidMergeSort(std::vector&array,intfront,intend){//front與end為矩陣範圍if(front>permute(vector&nums){vector>re;_permu(nums,0,re);returnre;}private:void_permu(vector&nums,intstart,vector>&re){if(start>=nums.size()){re.push_back(nums);return;}for(inti=start;i#include#include#includeusingnamespacestd;vectormyprime;intprime[1001];//value0meansprime,1meansmultipleintmain(){for(inti=2;i<=sqrt(1000);i++){for(intj=i*i;j<=1000;j=j+i){prime[j]=1;}}for(inti=2;i<=1000;i++){if(prime[i]==0){myprime.push_back(i);printf("%d",i);}}return0;}Q10.bitwise比大小[link]intcompare(uint32_ta,uint32_tb){uint32_tdiff=a^b;//找到兩者間不一樣的bit裡面最左邊那個if(!diff)return0;//001xxxxx->00100000diff|=diff>>1;diff|=diff>>2;diff|=diff>>4;diff|=diff>>8;diff|=diff>>16;diff^=diff>>1;//最後針對這個最左邊不一樣的bit看看是a擁有還是b擁有returna&diff?1:-1;}socketprogrammingread()跟recv()的差別?[link]ssize_tread(intsockfd,void*buf,size_tlen);ssize_trecv(intsockfd,void*buf,size_tlen,intflags);sockfd-sd是socket的描述符,即是前個Example的sockfd。

buf-一個緩衝區,讓Socket能把接收到的資料塞進裡頭。

len-即是buf的大小。

flags-相比最基本的read(),recv()的參數中多了這個旗標,flags代表接收的相關細節,通常是設定為0,也存在其他巨集處理一些特殊要求,比如blocking/nonblocking與超額接收等等,這部分細節可參見man-pages。

--MorefromYu-PuWuFollowLovepodcastsoraudiobooks?Learnonthegowithournewapp.TryKnowableRecommendedfromMediumBernardWillerAPIslikeReST,SOAPandotherstatetransferacronymsJusabeGuedesinSkyHubLabsElixirforJavaDevelopers,EpisodeIMuhammadLuqmaninInfoSecWrite-upsWrite-Up10-TryHackMe-LinuxChallengesNaomiBurgessinWezenHumansandMachines — PartnersnotEnemiesAurélioBuarqueinEngAppByeReactNative,welcomeFlutter!ChristianPichardocs371p-ChristianPichardoEyvazAhmadzadaMyGSoCJourney:Week2FrayinSkyfleetCaptain’sLogACloserLookat“Hello,World!”inCXAboutHelpTermsPrivacyGettheMediumappGetstartedYu-PuWu19FollowersFollowMorefromMediumKaiTHMWWBuddyWalk-ThroughEdwardPetersonWhereHaveAlltheFlowersGone?EverLend.appEverLend.appYusjayAbdullahiTHINKIUMisandall-in-onepublicBlockchainnetworkthatoperatesthroughamulti-layer…HelpStatusWritersBlogCareersPrivacyTermsAboutKnowable



請為這篇文章評分?