摘要:博主接下來將會(huì)整理一些語言中常見的問題和坑,再看博主解釋的時(shí)候可以自己思考一下變量的聲明和定義有什么區(qū)別答變量的定義為變量分配地址和存儲(chǔ)空間,變量的聲明不分配地址。指針操作超過了變量的作用域范圍如返回局部變量的地址。
博主接下來將會(huì)整理一些語言中常見的問題和坑,再看博主解釋的時(shí)候可以自己思考一下
1.變量的聲明和定義有什么區(qū)別?
答:變量的定義為變量分配地址和存儲(chǔ)空間,變量的聲明不分配地址。
一個(gè)變量的可以在多個(gè)地方聲明,在只能在一個(gè)地方定義。加上extern修飾的是變量的聲明,說明將這個(gè)變量在文件后面定義或者在文件以外
說明:
很多時(shí)候一個(gè)變量,只是聲明不分配內(nèi)存空間,直到使用時(shí)才初始化,分配內(nèi)存
for example:外部變量
#includeint main(){ extern int a;//注意在這里是聲明不是定義聲明a已經(jīng)是一個(gè)已經(jīng)定義了的外部變量,聲明外部變量時(shí)可以將變量的類型去掉 extern a;}int a;//此處是定義,定義了a為整型的外部變量
指針常量和常量指針有什么區(qū)別
答:指針常量是定義了一個(gè)指針,這個(gè)指針的值只能夠在定義是初始化,在其他地方不能夠改變。而常量指針是定義了一個(gè)指針,這個(gè)指針指向了一個(gè)只讀對(duì)象,不能通過常量指針來修改這個(gè)對(duì)象的值,但這個(gè)對(duì)象本身不一定是常量。
注意:
無論是常量指針還是指針常量,其最大的用途就是作為函數(shù)的參數(shù),保證實(shí)參在調(diào)用的時(shí)候的不可改變特性
#includeint main(){ int a = 1; int* const p1 = &a;//p1為指針常量 const int* p2 = &a;//p2為常量指針}
strlen和sizeof的區(qū)別
答:1.sizeof是一個(gè)操作符,而strlen是一個(gè)庫函數(shù)
2.sizeof的參數(shù)可以是數(shù)據(jù)類型,也可以是變量,而strlen只能以‘/0‘結(jié)尾的字符串作為參數(shù)
3.編譯器在編譯時(shí)就已經(jīng)計(jì)算出sizeof的結(jié)果了,而strlen必須在運(yùn)行時(shí)才能計(jì)算出來
4.sizeof計(jì)算出來的是數(shù)據(jù)類型所占的內(nèi)存大小,而strlen計(jì)算的是字符串實(shí)際的長度
5.數(shù)組做sizeof的參數(shù)不退化,而傳遞給指針strlen就退化成指針了
結(jié)構(gòu)體可以直接賦值嗎?
答:聲明時(shí)可以直接初始化,同一結(jié)構(gòu)體的不同對(duì)象之間也可以直接賦值,但結(jié)構(gòu)體中含有指針成員時(shí)一定要特別小心?。。。。。。。∮锌赡芏鄠€(gè)指針指向了同一塊內(nèi)存時(shí)某個(gè)指針釋放了這一段內(nèi)存,可能會(huì)導(dǎo)致其他指針的非法操作。因此在釋放前一定要保證其他指針不在使用這一塊空間
sprintf,strcpy,memcpy有什么區(qū)別?
1.操作對(duì)象不一樣,strcpy操作的兩個(gè)對(duì)象均為字符串,sprintf的操作源對(duì)象可以是多種數(shù)據(jù)類型,目的操作對(duì)象是字符串,memcpy的兩個(gè)對(duì)象是兩個(gè)任意可操作內(nèi)存的地址,并不限制于任何數(shù)據(jù)類型
2.執(zhí)行效率不一樣memcpy效率最高,將一個(gè)數(shù)組置零的最快方法就是使用memcpy,strcpy次之,而sprintf效率最低
3.實(shí)現(xiàn)功能不同,strcpy?主要實(shí)現(xiàn)字符串變量間的拷貝,sprintf?主要實(shí)現(xiàn)其他數(shù)據(jù)類型格式到字?符串的轉(zhuǎn)化,memcpy?主要是內(nèi)存塊間的拷貝。?「注意」:strcpy、sprintf?與memcpy?都可以實(shí)現(xiàn)拷貝的功能,但是針對(duì)的對(duì)象不同,根據(jù)實(shí)際需求,來?選擇合適的函數(shù)實(shí)現(xiàn)拷貝功能
#define和const用什么區(qū)別?
答:1.編譯器處理方式不同:#define宏是在預(yù)處理階段展開,不能對(duì)宏定義進(jìn)行調(diào)試,而const常量是在編譯階段使用.
?2.類型和安全檢查不同:#define宏沒有類型,不做任何類型檢查,僅僅是代碼展開,可能產(chǎn)生邊際效應(yīng)等錯(cuò)誤,而const常量有具體類型,在編譯階段會(huì)執(zhí)行類型檢查和作用域檢查;
3. 存儲(chǔ)方式不同:#define宏僅僅是代碼展開,在多個(gè)地方進(jìn)行字符串替換,不會(huì)分配內(nèi)存,存儲(chǔ)于程序的代碼段中,而const常量會(huì)分配內(nèi)存(可以是在堆中也可以是在棧中),但只維持一份拷貝,存儲(chǔ)于程序的數(shù)據(jù)段中。?
定義域不同:#define宏不受定義域限制,而const常量只在定義域內(nèi)有效
const定義常量從匯編的角度來看,只是給出了對(duì)應(yīng)的內(nèi)存地址,而不是象#define一樣給出的是立即數(shù),所以,const定義的常量在程序運(yùn)行過程中只有一份拷貝(因?yàn)槭侨值闹蛔x變量,存在靜態(tài)區(qū)),而?#define定義的常量在內(nèi)存中有若干個(gè)拷貝。
(6)?有些集成化的調(diào)試工具可以對(duì)const常量進(jìn)行調(diào)試,但是不能對(duì)宏常量進(jìn)行調(diào)試。
(7)?提高了效率。?編譯器通常不為普通const常量分配存儲(chǔ)空間,而是將它們保存在符號(hào)表中,這使得它成為一個(gè)編譯期間的常量,沒有了存儲(chǔ)與讀內(nèi)存的操作,使得它的效率也很高。
(8)?宏替換只作替換,不做計(jì)算,不做表達(dá)式求解;宏預(yù)編譯時(shí)就替換了,程序運(yùn)行時(shí),并不分配內(nèi)存。
?
懸掛的指針和野指針有什么區(qū)別?
答:1.懸掛的指針:當(dāng)指針?biāo)赶虻膶?duì)象已經(jīng)被釋放了但是該指針沒有發(fā)生任何的改變,仍然指向已經(jīng)被回收的那一塊空間在這種情況下該指針被稱為懸掛的指針
2.野指針:未初始化的指針被稱為野指針
typedef和#define有什么區(qū)別?
1.用法不同:typedef?用來定義一種數(shù)據(jù)類型的別名,增強(qiáng)程序的可讀性。define?主要用來定義?常量,以及書寫復(fù)雜使用頻繁的宏。
?執(zhí)行時(shí)間不同:typedef?是編譯過程的一部分,有類型檢查的功能。define?是宏定義,是預(yù)編譯的部分,其發(fā)生在編譯之前,只是簡(jiǎn)單的進(jìn)行字符串的替換,不進(jìn)行類型的檢查。
?作用域不同:typedef?有作用域限定。define?不受作用域約束,只要是在define?聲明后的引用?都是正確的。?
對(duì)指針的操作不同:typedef?和define?定義的指針時(shí)有很大的區(qū)別。?
特別要注意:typedef?定義是語句,因?yàn)榫湮惨由戏痔?hào)。而define?不是語句,千萬不能在句尾加分號(hào)!?。。。。。。。。。。。。。。。。。。。。。。?br />
?
如何避免野指針??
1.指針變量聲明時(shí)沒有初始化 。方案:在指針聲明時(shí)初始化,可以是具體的地址也可以用NULL來初始化。
2.指針變量被free或者delete后沒有置成NULL。方案:指針指向的內(nèi)存空間被釋放后指針應(yīng)該指向NULL。
3. 指針操作超過了變量的作用域范圍如返回局部變量的地址。方案:在變量作用域結(jié)束前釋放變量的地址空間并讓其指向NULL
棧和隊(duì)列有什么區(qū)別
棧和隊(duì)列都是存儲(chǔ)結(jié)構(gòu)。棧是先進(jìn)后出,而隊(duì)列是先進(jìn)先出
補(bǔ)充:
棧區(qū)和堆區(qū)的區(qū)別:堆區(qū)的存儲(chǔ)是“順序隨意的“而棧區(qū)是”先進(jìn)后出“棧由編譯器自動(dòng)分配釋放,存放函數(shù)的參數(shù)值局部變量的值等。類似于數(shù)據(jù)結(jié)構(gòu)的棧。堆一般是由程序員手動(dòng)釋放
全局變量和局部變量有什么區(qū)別?操作系統(tǒng)和編譯器是如何知道的?
1.全局變量是整個(gè)程序都可訪問的變量,誰都可以訪問,生存期在整個(gè)程序從運(yùn)行到結(jié)束(在程序結(jié)束時(shí)所占內(nèi)存釋放)。
2. 局部變量存在于模塊(子程序,函數(shù))中,只有所在模塊可以訪問,其他模塊不可直接訪問,模塊結(jié)束(函數(shù)調(diào)用完畢),局部變量消失,所占據(jù)的內(nèi)存釋放。
?3.操作系統(tǒng)和編譯器,可能是通過內(nèi)存分配的位置來知道的,全局變量分配在全局?jǐn)?shù)據(jù)段并且在程序開始運(yùn)行的時(shí)候被加載.局部變量則分配在堆棧里面
?
c語言中有那些不同的存儲(chǔ)類說明符?
答: auto ,register,static,extern?
?變量的范圍是什么?變量在c語言中的作用域怎樣
答:變量的范圍是程序的一部分,可以直接訪問該變量。在c語言中所有標(biāo)識(shí)符都在靜態(tài)范圍內(nèi)
如果沒有分號(hào)怎樣打印”hello world"
#include
int main()
{
if(printf("hello world))
{
}?
}
什么是NULL?
?NULL是指針沒用指向有效的位置,理想情況下,如果聲明時(shí)不知道指針的值,應(yīng)該將其初始化為NULL,當(dāng)指針?biāo)赶虻膬?nèi)存被釋放的時(shí)候,我們應(yīng)該將指針置為NULL
什么是內(nèi)存泄漏?為什么要避免他??
程序員在堆區(qū)開辟了一塊內(nèi)存而忘記釋放它時(shí)就會(huì)發(fā)生內(nèi)存泄漏。從定義可以看的出來內(nèi)存泄漏是比較嚴(yán)重的問題,永遠(yuǎn)不會(huì)停止
什么是局部靜態(tài)變量?他們有什么用?
局部靜態(tài)變量是一個(gè)變量,其生命周期并不以聲明他的函數(shù)調(diào)用而結(jié)束。它延長到整個(gè)程序的壽命。所有對(duì)該函數(shù) 調(diào)用都共享局部靜態(tài)變量,靜態(tài)變量可以用來計(jì)算調(diào)用函數(shù)的次數(shù)
局部變量未初始化默認(rèn)值為0
什么是靜態(tài)函數(shù)?他們有什么作用?
在c言中函數(shù)默認(rèn)都是全局的,在函數(shù)前面加上static修飾使其變?yōu)殪o態(tài)的和全局函數(shù)不同的是對(duì)靜態(tài)函數(shù)的訪問僅限于聲明他們的文件,因此當(dāng)我們想要限制函數(shù)訪問時(shí)我們可以將其設(shè)置為靜態(tài)的
#include<>和#include""的區(qū)別是什么?
#include<>會(huì)先到系統(tǒng)指定目錄尋找頭文件
而#include""先到項(xiàng)目所在目錄尋找頭文件,如果沒有找到再到系統(tǒng)指定目錄尋找頭文件
變量命名的規(guī)則是什么??
變量名的開頭只能是字母或者下劃線?。變量名由數(shù)字,字母,下劃線組成
數(shù)組的特點(diǎn)是什么?
同一個(gè)數(shù)組中所有的元素?cái)?shù)據(jù)類型都是相同的?同時(shí)數(shù)組中所有成員在內(nèi)存中的地址都是連續(xù)的?
數(shù)組的分類
數(shù)組的分類:數(shù)組可以分為靜態(tài)數(shù)組和動(dòng)態(tài)數(shù)組
靜態(tài)數(shù)組:類似int arr[90];在程序運(yùn)行時(shí)確定數(shù)組的大小,運(yùn)行過程中不能改變數(shù)組的大小
動(dòng)態(tài)數(shù)組:主要是在堆區(qū)申請(qǐng)的空間,數(shù)組的大小是在運(yùn)行過程中確定的?。?!可以更改數(shù)組的大小
一維數(shù)組不初始化,部分初始化,完全初始化的特點(diǎn)??
1.?不初始化:如果是局部數(shù)組?數(shù)組元素的內(nèi)容隨機(jī)?如果是全局?jǐn)?shù)組,數(shù)組的元素內(nèi)容為0
2.部分初始化:未被初始化的部分?動(dòng)補(bǔ)0
3.完全初始化:如果?個(gè)數(shù)組全部初始化?可以省略元素的個(gè)數(shù)?數(shù)組的??由初始化的個(gè)數(shù)確定
指針和指針變量有什么區(qū)別??
1.指針:在內(nèi)存中每一個(gè)字節(jié)都有一個(gè)地址?,這個(gè)地址的編號(hào)就是指針。也就是說指針就是地址
2.指針變量:指針變量本質(zhì)也是一個(gè)變量,用來保存地址。所以指針變量和指針是截然不同的概念
?在使用realloc給已分配的堆區(qū)追加空間需要注意什么?
記得用指針變量保存realloc的返回值?
聯(lián)合體和共用體的區(qū)別是什么?
在結(jié)構(gòu)體中成員擁有獨(dú)立的空間,
而共用體共享一塊空間,每一個(gè)共用體的成員能訪問共用區(qū)的空間大小是由成員自身的類型所決定?
如何理解淺拷貝和深拷貝?
1.?當(dāng)結(jié)構(gòu)體中有指針成員的時(shí)候容易出現(xiàn)淺拷?與深拷?的問題。
2.淺拷?就是,兩個(gè)結(jié)構(gòu)體變量的指針成員指向同?塊堆區(qū)空間,在各個(gè)結(jié)構(gòu)體變量釋放的時(shí)候會(huì)出現(xiàn)多次釋放同?段堆區(qū)空間
3.深拷?就是,讓兩個(gè)結(jié)構(gòu)體變量的指針成員分別指向不同的堆區(qū)空間,只是空間內(nèi)容拷??份,這樣在各個(gè)結(jié)構(gòu)體變量釋放的時(shí)候就不會(huì)出現(xiàn)多次釋放同?段堆區(qū)空間的
普通局部變量,普通全局變量,靜態(tài)局部變量,靜態(tài)全局變量的區(qū)別
?普通局部變量:?存在棧區(qū)、不初始化內(nèi)容隨機(jī)、只在定義所在的復(fù)合語句中有效、符合語句結(jié)束變量空間釋放
普通全局變量?:存在全局區(qū)、不初始化內(nèi)容為0、進(jìn)程結(jié)束空間才被釋放,能被當(dāng)前源?件或其他源?件使?,只是其他源?件使?的時(shí)候,記得使?extern修飾
靜態(tài)局部變量:?存在全局區(qū)、不初始化內(nèi)容為0、整個(gè)進(jìn)程結(jié)束空間才被釋放,只能在定義所在的復(fù)合語句中有效
靜態(tài)全局變量?:存在全局區(qū)、不初始化內(nèi)容為0、整個(gè)進(jìn)程結(jié)束空間才被釋放,只能被當(dāng)前源?件使?
描述一下gcc的編譯過程
gcc編譯過程分為4個(gè)階段:預(yù)處理、編譯、匯編、鏈接。
預(yù)處理:頭?件包含、宏替換、條件編譯、刪除注釋
編譯:主要進(jìn)?詞法、語法、語義分析等,檢查?誤后將預(yù)處理好的?件編譯成匯編?件。
匯編:將匯編?件轉(zhuǎn)換成??進(jìn)制?標(biāo)?件
鏈接:將項(xiàng)?中的各個(gè)?進(jìn)制?件+所需的庫+啟動(dòng)代碼鏈接成可執(zhí)??件
?
#和##的作用是什么??
#是把宏參數(shù)轉(zhuǎn)換為字符串的運(yùn)算符,而##是把兩個(gè)宏參數(shù)連接的運(yùn)算符?
extern "C"?
extern "c“的作用是為了能夠正確的實(shí)現(xiàn)c++代碼調(diào)用c語言代碼。加上extern "C"后會(huì)指示編譯器這一部分代碼按c語言的編譯方式進(jìn)行編譯,而不是c++
(void *)ptr和(*(void** ))ptr的結(jié)果是否相同?其中ptr為同一個(gè)指針
局部變量是否可以和全局變量重名??
能,局部會(huì)屏蔽全局。要用全局變量,需要使用”::”?;局部變量可以與全局變量同名,在函數(shù)內(nèi)引用這個(gè)變量時(shí),會(huì)用到同名的局部變量,而不會(huì)用到全局變量。對(duì)于有些編譯器而言,在同一個(gè)函數(shù)內(nèi)可以定義多個(gè)同名的局部變量,比如在兩個(gè)循環(huán)體內(nèi)都定義一個(gè)同名的局部變量,而那個(gè)局部變量的作用域就在那個(gè)循環(huán)體內(nèi)。
?
如何引用一個(gè)已定義過的全局變量??
?extern?可以用引用頭文件的方式,也可以用extern關(guān)鍵字,如果用引用頭文件方式來引用某個(gè)在頭文件中聲明的全局變理,假定你將那個(gè)編寫錯(cuò)了,那么在編譯期間會(huì)報(bào)錯(cuò),如果你用extern方式引用時(shí),假定你犯了同樣的錯(cuò)誤,那么在編譯期間不會(huì)報(bào)錯(cuò),而在連接期間報(bào)錯(cuò)。
全局變量可不可以定義在多個(gè)可被包含的.c文件包含頭文件。為什嗎??
?可以,在不同的C文件中以static形式來聲明同名全局變量。?可以在不同的C文件中聲明同名的全局變量,前提是其中只能有一個(gè)C文件中對(duì)此變量賦初值,此時(shí)連接不會(huì)出錯(cuò).
語句for(;1;)有什么問題?他的意思是什么??
和while(1)相同死循環(huán)?
do while();和while有什么區(qū)別?
一個(gè)先循環(huán)一遍在判斷,一個(gè)判斷以后贊循環(huán)??
#includeint main(){char a;char *str=&a;strcpy(str,"hello");printf(str);return 0;}
?這段代碼有什么問題?
?沒有為str分配內(nèi)存空間,將會(huì)發(fā)生異常問題出在將一個(gè)字符串復(fù)制進(jìn)一個(gè)字符變量指針?biāo)傅刂?。雖然可以正確輸出結(jié)果,但因?yàn)樵浇邕M(jìn)行內(nèi)在讀寫而導(dǎo)致程序崩潰。
int(*s[10])(int)表示什么意思?
int(*s[10)(int)是一個(gè)函數(shù)指針數(shù)組,每一個(gè)元素指向了一個(gè)int func(int param)的函數(shù)?
以下代碼有什么問題???
#includeint main(){char*s="AAA";printf("%s",s);s[0]="1";printf("%s",s);
?"AAA"是常量。s是指針變量,指向了這個(gè)字符串。在聲明時(shí)就有問題。應(yīng)該寫成const char *s="AAA";又因?yàn)槭浅A?,所以不能修改,所以s[0]=’1‘是非法的
下面這段代碼會(huì)輸出什么??
void func(void){unsigned int a=6;int b=-20;(a+b>6)?puts(">6"):puts("<=6");}
>6
當(dāng)有符號(hào)和無符號(hào)運(yùn)算時(shí),同一轉(zhuǎn)成無符號(hào),而在有符號(hào)最高位的1表示負(fù)數(shù),當(dāng)轉(zhuǎn)成無符號(hào)數(shù)時(shí)最高位不再表示負(fù)數(shù)所以是一個(gè)很大的數(shù)??
?下面這代碼的結(jié)果是什么?
include int main(void) { int i = -1; if(i = 0) printf("i = %d/n",i); else if(i = 1) printf("i = %d/n",i); else printf("i = %d/n",i); return 0; }
1,=號(hào)是賦值而不是判斷相等
?這段代碼有什么問題?
#include#includeint main(){ char s[] = "abcdefg"; char d[] = "123"; strcpy(d, s); printf("%s %s", s, d);}
結(jié)果:
?咦?很奇怪,輸出d是正確的,s發(fā)生了截?cái)?!要說越界也應(yīng)該是d錯(cuò)啊,這是什么情況?大家不要著急,我們一步步來分析調(diào)試找原因。
??????首先我們先來回顧一下strcpy函數(shù)的原理,把一個(gè)字符串復(fù)制到一個(gè)字符串上并在末尾追加空字符,但沒有越界檢驗(yàn),安全性堪憂。但此題看運(yùn)行結(jié)果是復(fù)制成功了,不應(yīng)該是越界嗎?
??????那再往下就不能靠分析了,得調(diào)試程序找錯(cuò)了,說白了現(xiàn)在問題就在越界這里。為什么了這是因?yàn)榫植孔兞渴欠旁跅^(qū)的,棧區(qū)是先使用高地址在使用低地址。由于在這個(gè)編譯器里面,變量之間的存放間隔很小,當(dāng)strcpy越界的時(shí)候,就將s里面的類容給覆蓋了
?
#includeint main(){char *ptr;if(ptr=(char*)malloc(0)==NULL)printf("Got a null pointer);elseprintf("Got a valid pointer);return 0;}
以上代碼會(huì)輸出什么?
Got? a vail ponter
?1.找錯(cuò)
void test (){char string [10];char *str1="0123456789";strcpy(string ,str1);}
這里string數(shù)組越界,因?yàn)樽址L度為10,還有一個(gè)結(jié)束符‘/0’。所以總共有11個(gè)字符長度。string數(shù)組大小為10,這里越界了。
注意:使用strcpy函數(shù)的時(shí)候一定要注意前面目的數(shù)組的大小一定要大于后面字符串的大小,否則便是訪問越界。
?
void test2(){char string [10],str1[10];for(i=0;i<10;i++){str1[i]="a";}strcpy(string,str1);}
這里有一個(gè)一眼就能看出的問題,那就是變量i沒有定義,這在代碼編譯階段編譯器可以幫你發(fā)現(xiàn),很容易搞定。然而很多問題是自己造成的漏洞,編譯器是幫不上什么忙的。這里最大的問題還是str1沒有結(jié)束符,因?yàn)閟trcpy的第二個(gè)參數(shù)應(yīng)該是一個(gè)字符串常量。該函數(shù)就是利用判斷第二個(gè)參數(shù)的結(jié)束符來得到是否拷貝完畢。所以在for循環(huán)后面應(yīng)加上str1p[9]?=?‘/0’;
注意:字符數(shù)組和字符串的最明顯的區(qū)別就是字符串會(huì)被默認(rèn)的加上結(jié)束符‘/0’。
?
void test3(char *str){char string[10];if(strlen(string )<=10){strcpy(string ,str);}}
?這里的問題仍是越界問題。strlen函數(shù)得到字符串除結(jié)束符外的長度。如果這里是<=10話,就很明顯越界了。
?下面這段代碼的運(yùn)行結(jié)果是什么?
#includeint sum(int a){auto int c=0;static int b=3;c+=1;b+=2;return a+b+c;}int main(){int i=0;int a=2;for(i=0;i<5;i++){printf("%d ”,sum(a));}return 0;}
運(yùn)行結(jié)果是:8,10,12,14,16,
在求和函數(shù)sum里面c是auto變量,根據(jù)auto變量特性知每次調(diào)用sum函數(shù)時(shí)變量c都會(huì)自動(dòng)賦值為0.b是static變量,根據(jù)static變量特性知每次調(diào)用sum函數(shù)時(shí)變量b都會(huì)使用上次調(diào)用sum函數(shù)時(shí)b保存的值。
簡(jiǎn)單的分析一下函數(shù),可以知道,若傳入的參數(shù)不變,則每次調(diào)用sum函數(shù)返回的結(jié)果,都比上次多2.所以答案是:8,10,12,14,16,
?
int func(int a){int b;switch(a){case 1:b=30;case 2:b=20;case 3:b=16;default :b=0;}return b;}
?func(1)的值為多少?
因?yàn)閏ase語句中沒有break,所以無論如何傳給函數(shù)的參數(shù)是多少結(jié)果都是0
a[q-p]=??
int a[3]; a[0]=0; a[1]=1; a[2]=2; int *p, *q; p=a; q=&a[2]; 很明顯:a[q - p] = a[2] = 2;
下面我們來看一段很有趣的代碼
#include int main() { int arr[] = { 6, 7, 8, 9, 10 }; int *ptr = arr; *(ptr++) += 123; printf("%d,%d/n", *ptr, *(ptr++)); return 0; }
結(jié)果為 8,7
程序運(yùn)行結(jié)果為:
8,7
1.解釋:*(ptr++)?+=?123這句代碼中,使用了后++
所以效果相當(dāng)于:*ptr(6)+123=129;
ptr+=1;
也就是運(yùn)行后*ptr指向larr[1];
2.解釋:printf(“%d,%d/n”,?ptr,?(ptr++));這句代碼的執(zhí)行涉及到匯編的函數(shù)的參數(shù)的壓棧過程是從后面的參數(shù)開始?jí)簵5?,所?(ptr++)會(huì)先被壓棧,導(dǎo)致ptr++首先生效(引用別人的?因?yàn)槲也粫?huì)匯編)
所以往棧里壓入*ptr時(shí),此時(shí)的ptr已經(jīng)變成指向arr[2]了
同理一下代碼的運(yùn)行結(jié)果為8,8;
?
#include int main() { int arr[] = { 6, 7, 8, 9, 10 }; int *ptr = arr; *(ptr++) += 123; printf("%d,%d/n", *ptr, *(++ptr)); return 0; }
如果不是很理解的話,我們可以看一下這個(gè)例子
int i=2;printf("%d/n",i++);printf("%d/n",i);
?原理是一樣的
總結(jié):
?(*p)++和*p++的概括
(*p)++指的是先取出p指向的存儲(chǔ)單元中的內(nèi)容,然后將取出的數(shù)值加1,而p仍然指向原來的存儲(chǔ)單元。
*p++則指的是先取出p指向的存儲(chǔ)單元中的內(nèi)容,然后將p值加1,此時(shí)p不再指向原來的存儲(chǔ)單元。
表達(dá)式(*p)++和*p++具有不同的含義,(*p)++并沒有修改指針p的指向,而*p++則修改了指針p的指向。
?
?以下代碼的結(jié)果是什么?
#includeint i;int main(){--i;if(i>sizeof(i)){printf("大于");}else{printf("小于“);}return 0;}
?結(jié)果為:大于:解釋首先全局變量未初始化默認(rèn)值為0,--i之后變成-1,但是sizeof計(jì)計(jì)算出來的是無符號(hào)整型,在比較的時(shí)候會(huì)先將-1先轉(zhuǎn)成無符號(hào)數(shù)那么-1在內(nèi)存中的最高位不在是符號(hào)位,那么這將會(huì)是一個(gè)很大的數(shù)所以是大于
#includeint main(){ union Data { struct { int x; int y; }s; int x; int y; }d; d.x=1; d.y=2; d.s.x=d.x*d.x; d.s.y=d.y+d.y; printf("%d %d",d.s.x,d.s.y);}
上面這段代碼的運(yùn)行結(jié)果是什么?
答:4,8.解釋union中的成員相對(duì)于基地址的偏移量都為0,共用一塊內(nèi)存
d.x,d.y的起始位置都相同,共享內(nèi)存空間。給任意一個(gè)賦值另外一個(gè)也會(huì)被賦予相同的值?
x y s.y s.x
x,ys.x s.y d.x=1 1 0 d.y=2 2 0 d.s.x=d.x*d.x 4 0 d.s.y=d.y+d.y 4 8
?最后分享一些比較坑的
優(yōu)先級(jí)問題 | 表達(dá)式 | 誤以為的結(jié)果 | 實(shí)際結(jié)果 |
.的優(yōu)先級(jí)高于*,->可以消除這個(gè)問題 | *p.f | p所指向?qū)ο蟮淖侄蝔 (*p).f | p對(duì)f取偏移,作為指針然后進(jìn)行解除引用操作*(p.f) |
[]的優(yōu)先級(jí)高于* | int *ap[] | ap是一個(gè)指向int數(shù)組的指針 int(*ap)[] | ap是個(gè)元素為int指針數(shù)組int(*ap[]) |
函數(shù)()高于* | int*fp() | fp是一個(gè)指針,所指函數(shù)返回int int(*fp)() | fp是個(gè)函數(shù)返回int* int*(fp()) |
==和!=高于位操作符 | (val&mask!=0)? | (val&mask)!=0 | val&(mask!=0) |
==和!=高于= | c=getchar()!=EOF | (c=getchar())!=EOF | c=(getchar()!=EOF) |
算數(shù)運(yùn)算高于移位運(yùn)算 | msb<<4+lsb | (msb<<4)+lsb | msb<<(4+lsb) |
逗號(hào)運(yùn)算符最低 | i=1,2 | i=(1,2) | (i=1),2 |
博主水平有限,如有錯(cuò)誤請(qǐng)指正,本文來自網(wǎng)絡(luò)收集和我自己的一些理解。如果覺得不錯(cuò)的可以點(diǎn)個(gè)贊,謝謝!
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/119305.html
摘要:在正式前端一些小細(xì)節(jié)前端掘金英文原文,翻譯未來的太讓人興奮了一方面,是全新的頁面布局方式另一方面,是酷炫的濾鏡顏色等視覺效果。老司機(jī)教你更好的進(jìn)行編程個(gè)技巧前端掘金并不總是容易處理。 CSS3 實(shí)現(xiàn)文字流光漸變動(dòng)畫 - 前端 - 掘金來自百度前端技術(shù)學(xué)院的實(shí)踐任務(wù):有趣的鼠標(biāo)懸浮模糊效果,參考:http://ife.baidu.com/course/d...,用CSS3實(shí)現(xiàn)了一下,順便...
摘要:實(shí)現(xiàn)不定期更新技巧前端掘金技巧,偶爾更新。統(tǒng)一播放效果實(shí)現(xiàn)打字效果動(dòng)畫前端掘金前端開源項(xiàng)目周報(bào)前端掘金由出品的前端開源項(xiàng)目周報(bào)第四期來啦。 Web 推送技術(shù) - 掘金騰訊云技術(shù)社區(qū)-掘金主頁持續(xù)為大家呈現(xiàn)云計(jì)算技術(shù)文章,歡迎大家關(guān)注! 作者:villainthr 摘自 前端小吉米 伴隨著今年 Google I/O 大會(huì)的召開,一個(gè)很火的概念--Progressive Web Apps ...
摘要:上面這三種均不造成重載,現(xiàn)在來說明原因。結(jié)論對(duì)于引用返回,返回的對(duì)象必須是棧幀銷毀后還存在的。全局,靜態(tài),未銷毀的函數(shù)棧幀當(dāng)中的都是可以的指針與引用如圖兩者底層實(shí)現(xiàn)差不多,引用是用指針模擬的。不建議聲明和定義分離,分離會(huì)導(dǎo)致鏈接錯(cuò)誤。 ...
摘要:此專欄文章是對(duì)力扣上算法題目各種方法的總結(jié)和歸納整理出最重要的思路和知識(shí)重點(diǎn)并以思維導(dǎo)圖形式呈現(xiàn)當(dāng)然也會(huì)加上我對(duì)導(dǎo)圖的詳解目的是為了更方便快捷的記憶和回憶算法重點(diǎn)不用每次都重復(fù)看題解畢竟算法不是做了一遍就能完全記住的所 ...
摘要:的最后一個(gè)大招就是替換一些傳統(tǒng)的服務(wù)端語言,例如,,等,在業(yè)務(wù)層上面使用來開發(fā)服務(wù)端完全不成問題。更多的的使用細(xì)節(jié)和技巧建議關(guān)注美團(tuán)博客大搜車論壇下一篇我們開啟如何結(jié)合和搭建一個(gè)開發(fā)環(huán)境和項(xiàng)目目錄 往期回顧 前面2期都講得是瀏覽器端的東西比較多,包括Webpack,雖然是Node處理的,但是還是瀏覽器端用的多,對(duì)于現(xiàn)在的前端開發(fā)來說,不懂一點(diǎn)服務(wù)端的東西,簡(jiǎn)直沒辦法活,一般的招聘要求都...
閱讀 2870·2021-09-22 15:43
閱讀 4796·2021-09-06 15:02
閱讀 858·2019-08-29 13:55
閱讀 1690·2019-08-29 12:58
閱讀 3081·2019-08-29 12:38
閱讀 1259·2019-08-26 12:20
閱讀 2274·2019-08-26 12:12
閱讀 3323·2019-08-23 18:35