華嵌課件-c語言授課及日志_第1頁
華嵌課件-c語言授課及日志_第2頁
華嵌課件-c語言授課及日志_第3頁
華嵌課件-c語言授課及日志_第4頁
華嵌課件-c語言授課及日志_第5頁
已閱讀5頁,還剩40頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

地址和指針的概念為了說清楚什么是指針,必須弄清楚數(shù)據(jù)在內(nèi)存中是如何存儲的,又是如何讀取的。內(nèi)存區(qū)的每一個字節(jié)有一個編號,這就是“地址”。如果在程序中定義了一個變量,在對程序進行編譯時,系統(tǒng)就會給這個變量分配內(nèi)存單元。1、按變量地址存取變量值的方式稱為“直接訪問”方式printf(″%d″,i);scanf(″%d″,&i);k=i+j;例如:地址和指針的概念另一種存取變量值的方式稱為“間接訪問”的方式。即,將變量i的地址存放在另一個變量中。在C語言中,指針變量是一種特殊的變量,它是存放地址的。假設(shè)我們定義了一個指針變量i_pointer用來存放整型變量的地址,它被分配地址為(3010)、(3011)、(3012)、(3013)的四個字節(jié)。可以通過語句:i_pointer=&i;將i的地址(2000)存放到i_pointer中。這時,

i_pointer的值就是(2000),即變量i所占用單元的起始地址。要存取變量i的值,可以采用間接方式:先找到存放“i的地址”的變量i_pointer

,從中取出i的地址(2000),然后到2000、2001、2002、2003字節(jié)取出i的值。指針和指針變量一個變量的地址稱為該變量的“指針”。例如,地址2000是變量i的指針。如果有一個變量專門用來存放另一變量的地址(即指針),則它稱為“指針變量”。上述的i_pointer就是一個指針變量。指針和指針變量的定義:指針變量的值(即指針變量中存放的值)是地址(即指針)。請區(qū)分“指針”和“指針變量”這兩個概念??偨Y(jié)變量:命名的內(nèi)存空間,用于存放各種類型的數(shù)據(jù)。變量名:變量名是給內(nèi)存空間取的一個容易記憶的名字。 通過變量名直接訪問內(nèi)存單元變量的地址:變量所使用的內(nèi)存空間的地址。變量值:在變量單元中存放的數(shù)值。即變量的內(nèi)容??偨Y(jié)地址:內(nèi)存單元的編號也叫做地址。指針:內(nèi)存單元地址稱為指針,即指針就是地址。指針變量:存放指針(地址)的變量稱為指針變量。(間接訪問)各種類型變量都有地址,通過地址(指針)或變量名訪問變量。直接訪問:在程序中使用變量名(變量地址)存取變量值的方式,稱為“直接訪問”方式。

間接訪問:定義一個指針變量來存放了一個變量的地址,通過指針變量存取變量的值,稱為“間接訪問”方式。指針變量的定義變量的指針和指向變量的指針變量定義一個指針變量定義指針變量的一般形式為基類型*指針變量名;int*ptr;說明指針變量的類型:指明了該指針指向的內(nèi)存空間所存儲的數(shù)據(jù)類型。定義中的“*”表示所定義的變量是指針變量。變量名是ptr,而非*ptr。指針變量的引用請牢記,指針變量中只能存放地址(指針),不要將一個整數(shù)(或任何其他非地址類型的數(shù)據(jù))賦給一個指針變量通過指針變量訪問整型變量給指針賦值通過&運算符為指針賦值,例如:ptr_var=&var;通過另一個指向相同類型數(shù)據(jù)項的指針變量對指針進行賦值,例如:ptr_var2=ptr_var;將地址直接賦值給指針變量int*ptr_var3=(int*)malloc(sizeof(int)); malloc()函數(shù)申請動態(tài)分配內(nèi)存空間,返回空間首地址; free()函數(shù)釋放不用內(nèi)存空間。 給指針變量賦值為符號常量NULL例如:float*ptr_var4=NULL;說明:NULL是一個空指針,表示該指針變量的值沒有意義,作用是為了避免對沒有被初始化的指針變量的非法引用,NULL的定義在“stdio.h”中。給指針賦值數(shù)組的首地址賦予指針變量。 例如:inta[5],*p;p=a;或?qū)憺椋簆=&a[0];或:inta[5],*p=a;字符串首地址賦予指針變量。 例如:char*pc;pc="Hello"; 或?qū)憺椋篶har*pc="Hello"; 說明:并不是把整個字符串裝入指針變量,而是把存放該字符串的首地址裝入指針變量。函數(shù)的入口地址賦予指針變量。例如: int(*pf)(void);intfunc(void) pf=func;/*func為函數(shù)名*/指針運算符&是取地址運算符(一元運算符),它返回操作數(shù)的內(nèi)存地址例如:intvar=12,*ptr; ptr=&var;*是取內(nèi)容運算符,是&的反運算符,它也是一元運算符,返回指針指向的內(nèi)存位置中的值例如:intvar=12,*ptr=&var; inttemp=*ptr; //等價于temp=var;指針運算符對“&”和“*”運算符說明:(“&”和“*”兩個運算符的優(yōu)先級別相同,但按自右而左方向結(jié)合)如果已執(zhí)行了語句pointer_1=&a;pointer_2=&b;(1)pointer_2=&*pointer_1?先進行*

pointer_1的運算,它就是變量a,再執(zhí)行&運算。&*pointer_1與&a相同,即變量a的地址,就是將&a(a的地址)賦給pointer_2

指針運算符指針運算符(2)

*&a?&*a?先進行&a運算,得a的地址,再進行*運算。即&a所指向的變量,也就是變量a。*&a和*pointer_1的作用是一樣的,它們都等價于變量a。即*&a與a等價。(3)

(*pointer_1)++和*pointer_1++*pointer_1++:++和*為同一優(yōu)先級別,而結(jié)合方向為自右而左,因此它相當于*(pointer_1++)。由于++在pointer_1的右側(cè),是“后加”,因此先對pointer_1的原值進行*運算,得到a的值,然后使pointer_1的值改變,這樣pointer_1不再指向a了。(*pointer_1)++:*pointer_1相當a,所以整個表達式相當于a++指針的算術(shù)運算只能進行加法和減法運算:+-++--+=-=兩種形式:指針±整數(shù)或者指針-指針指針與整型值加減的結(jié)果是指針,表示使該指針指向該指針下移或上移存儲單元個數(shù)(整型值)之后的內(nèi)存地址。存儲單元的大小就是該指針的數(shù)據(jù)類型所需的內(nèi)存大小。指針與指針的減運算要求相減的兩個指針屬于同一類型,其結(jié)果是整數(shù),表示兩個指針之間的數(shù)據(jù)的個數(shù)。//不是字節(jié)數(shù)例如: intvar,*ptr_var; ptr_var=&var; ptr_var++; 假定var存儲在地址1000中,因為整數(shù)的長度是4個字節(jié),ptr_var的值將是1004在哪里有使用過指針-指針?指針的算術(shù)運算指針遞增時,將指向其類型的下一個元素的內(nèi)存位置,反之亦然操作意義++ptr_var或ptr_var++指向var后面的下一個整數(shù)--ptr_var或ptr_var--指向var前面的整數(shù)ptr_var+i指向var后面的第i個整數(shù)ptr_var-i指向var前面的第i個整數(shù)指針比較前提:兩個指針都指向相同類型的變量假設(shè)ptr_a和ptr_b分別指向a和b操作意義ptr_a<ptr_b如果a存儲在b的前面則返回trueptr_a<=ptr_b如果a存儲在b的前面,或兩個指針指向同一位置則返回trueptr_a==ptr_b如果兩個指針指向同一位置則返回trueptr_a!=ptr_b如果兩個指針指向不同位置則返回trueptr_a==NULL如果ptr_a是空值則返回true指針按地址傳遞指針可以作為參數(shù)把實參的地址傳給形參允許函數(shù)訪問內(nèi)存位置被調(diào)函數(shù)能夠修改主調(diào)程序的參數(shù)的值定義 getstr(char*ptr_str,int*ptr_int);使用 getstr(pstr,&var);指針和一維數(shù)組一個數(shù)組包含若干元素,每個數(shù)組元素都在內(nèi)存中占用存儲單元,它們都有相應(yīng)的地址。指針變量既然可以指向變量的地址,當然也可以指向數(shù)組和數(shù)組元素。所謂數(shù)組的指針(數(shù)組的名稱)是指數(shù)組的起始地址,也就是第一個元素的地址。數(shù)組的指針是個常量指針。數(shù)組元素的地址可以用兩種方式表示在數(shù)組元素前面加“&”符號 &ary[2]數(shù)組名+下標 ary+2引用數(shù)組元素下標法:inta[8]={2,4,6,8,10,12,14,16};a[i]?指針int*p=a;或者int*p=&a[0];注意:a代表數(shù)組首地址,而不是整個數(shù)組引用數(shù)組元素 *(p+i)、*(a+i)、p[i]、a[i]此時,p++是允許的,a++是錯誤的。執(zhí)行p++,p指向下一個元素,即a[1]。*p為a[1]的值。*p++,相當于*p,p++。*(p++)與*(++p)作用不同。(*p)++,表示將p所指向的元素值加1.數(shù)組作為參數(shù)傳遞一維數(shù)組元素作參數(shù)傳遞時,按值傳遞整個數(shù)組(數(shù)組名)當參數(shù)傳遞時,按地址傳遞,有以下三種等價的寫法:voidtest_array(chararray[]);voidtest_array(chararray[LEN]);voidtest_array(char*array);數(shù)組作為參數(shù)傳遞歸納起來,如果有一個實參數(shù)組,想在函數(shù)中改變此數(shù)組中的元素的值,實參與形參的對應(yīng)關(guān)系有以下4種情況:(1)形參和實參都用數(shù)組名,如:voidmain()voidf(intx[],intn){inta[10];{……

f(a,10);}}(2)實參用數(shù)組名,形參用指針變量。如:voidmain()voidf(int*x,intn){inta[10]; {……

f(a,10);} }數(shù)組作為參數(shù)傳遞(3)實參形參都用指針變量。例如:voidmain()voidf(int*x,intn){inta[10],*p=a; {……f(p,10); }}(4)實參為指針變量,形參為數(shù)組名。如:voidmain()voidf(intx[],intn){inta[10],*p=a;{……f(p,10)}}指向字符串常量的字符指針可以聲明字符指針直接指向字符串常量,例如char*pStr=“e”;字符指針pStr將指向字符常量“e”“e”為字符串常量,因此其值不能修改,例如代碼pStr[0]=‘h’;將引發(fā)一個錯誤區(qū)別字符數(shù)組Welcome\0字符串常量不能改變指向字符串變量的字符指針可以使用字符指針來存儲和訪問字符串聲明字符指針語法:char*pStr;聲明字符串:charstr[10]=“hello”;使用字符指針指向字符串:pStr=str;可以使用字符指針訪問字符串,例如pStr[0]=‘a(chǎn)’;該代碼將第一個字符修改為’a’char*pstr="e";charstr[]="e";pstr[0]='h'; str[0]='h';pstr="hello"; str="hello";字符串常量和字符串變量區(qū)別字符串常量和字符串變量一樣,都是一個一維字符數(shù)組。兩者的區(qū)別在于: 字符串變量的名字(一維字符數(shù)組名)及其所需的存儲空間是顯式定義的,并通過名字來引用相應(yīng)的字符串變量。而字符串常量所需的存儲空間是隱式定義的,并且其根本就沒有名字。字符數(shù)組和字符指針的區(qū)別字符數(shù)組字符指針字符數(shù)組由若干個元素組成,每一個元素是一個字符。characBuf[]={“hello”};字符指針變量中存放的是字符串的首地址,而不是把字符放到字符指針變量中。char*ptr={“hello”};對于字符數(shù)組,只能對各個元素賦值,或者通過strcpy()整體賦值。acBuf=”123”;//錯的字符指針變量可以直接通過賦值運算符,使用字符串對整體賦值。char*ptr;ptr=“hello”;新定義的數(shù)組在編譯時分配內(nèi)存單元,有確定的地址新定義的指針變量,無具體的值.解決辦法是,把一個已定義的字符數(shù)組的地址賦給這個指針變量雖然字符數(shù)組名也表示數(shù)組的首地址,但是卻不能通過賦值的方法改變字符指針變量的值是可以改變的,。字符數(shù)組和字符指針作返回值#include<stdio.h>char*print(){ characStr[]="helloworld"; returnacStr;}voidmain(){ char*pcStr;pcStr=print();puts(pcStr);}#include<stdio.h>char*print(){ char*pcStr="helloworld"; returnpcStr;}voidmain(){ char*pcStr;pcStr=print();puts(pcStr);}通過指針引用二維數(shù)組元素在C語言中,一個二維數(shù)組可以看成是一個一維數(shù)組,其中每個元素又是一個包含若干元素的一維數(shù)組。例如:inta[3][5];a[0]、a[1]和a[2]分別是包含五個元素的一維數(shù)組名,分別代表a數(shù)組元素的起始地址(即a[0]是第0行元素的首地址,a[1]是第1行元素的首地址)。a[i]和*(a+i)(無條件等價)都是第i行第0列元素的地址,那么a[i]+j、*(a+i)+j、&a[0][0]+3*i+j都是第i行第j列元素的地址。例如:inta[3][5],(*p)[5];p=a;對二維數(shù)組的引用有三種方式:下標法。如a[i][j]或p[i][j]。指針針法,如*(*(p+i)+j)或*(*(a+i)+j)。引用二維數(shù)組元素(1)用數(shù)組名表示二維數(shù)組的行地址inta[3][4];假設(shè)其首地址為2000 a為二維整型數(shù)組名,a=2000。(數(shù)組名總是代表數(shù)組的首地址) a+0就是第0行的首地址2000。即為a[0] a+1代表第一行首地址。為2008。即為a[1] a+2代表第二行首地址。即2016。即為a[2](2)用數(shù)組名表示二維數(shù)組元素地址 二維數(shù)組中a[0]、a[1]、a[2]都是地址, 則有:*(a+0)、*(a+1)和*(a+2)也是地址,它們分別是第0行、1行和2行的第0列地址。 因此,a[0]+1等介于*(a+0)+1,即&a[0][1]。 a[1]+2等介于*(a+1)+2,即&a[1][2]。 a[2]+3等介于*(a+1)+3,即&a[1][3]。 a[0][1]的值可表示為:*(a[0]+1)和*(*(a+0)+1) a[i][j]的值可表示應(yīng)為:*(a[i]+j)和*(*(a+i)+j)。指針與二維數(shù)組示例#include<stdio.h>#include<stdlib.h>voidmain(){ intaiNum[3][3]={{1,2,3},{4,5,6},{7,8,9}};int(*p)[5];inti,j; p=aiNum; for(i=0;i<3;i++){ for(j=0;j<3;j++) printf("%d\t",*(*(p+i)+j));} putchar('\n');for(i=0;i<3;i++){for(j=0;j<3;j++) printf("%d\t",*(p[i]+j));}putchar('\n');for(i=0;i<3;i++){for(j=0;j<3;j++) printf("%d\t",*(&p[0][0]+i*3+j));}putchar('\n');for(i=0;i<3;i++){for(j=0;j<3;j++) printf("%d\t",(*(p+i))[j]);}putchar('\n');}二維數(shù)組作為函數(shù)參數(shù)當二維數(shù)組名作為函數(shù)實參時,對應(yīng)的形參必須是一個行指針變量。和一維數(shù)組一樣,數(shù)組名傳送給變量的是一個地址值,因此,對應(yīng)的形參也必須是一個類型相同的指針變量,在函數(shù)中引用的將是主函數(shù)中的數(shù)組元素,系統(tǒng)只為形參開辟一個存放地址的存儲單元,而不可能在調(diào)用函數(shù)時為形參開辟一系列存放數(shù)組的存儲單元。intmain(){ intiNum[3][4]; …… fun(iNum); ……}fun(int(*iNum)[4]){ ……}fun(intarray[][4]){ ......}數(shù)組元素三種形式引用:⑴a[i][j]下標法⑵*(a[i]+j)用一維數(shù)組名⑶*(*(a+i)+j)用二維數(shù)組名指針數(shù)組指針數(shù)組就是其元素為指針的數(shù)組每一個元素都是指針變量說明指針數(shù)組的語法格式為:數(shù)據(jù)類型*指針數(shù)組名[常量表達式];例如:int*p1[6];指針數(shù)組主要用于字符串的操作例如:char*name[3]={“Rose”,“Smith”,“John”};注意:與一個指向二維數(shù)組的指針變量的區(qū)別,int(*p1)[6]和int*p1[6]之間的區(qū)別指針數(shù)組的示例#include<stdio.h>intmain(){ inti; char*menu[5]= {"aaa","bbbb","ccc",”dd","ee"}; for(i=0;i<5;i++){ puts(menu[i]); } return0;}char*pmenu[5],menu[5][10]={"aaa","bbbb","ccc",”dd","ee"};for(i=0;i<5;i++) pmenu[i]=menu[i];for(i=0;i<5;i++) puts(pmenu[i]);char(*pmenu)[10],menu[5][10]={"aaa","bbbb","ccc",”dd","ee"};pmenu=menu;for(i=0;i<5;i++){ puts(pmenu[i]);}結(jié)構(gòu)體指針結(jié)構(gòu)體指針是通過在結(jié)構(gòu)體變量名前放置一個星號(*)來進行聲明的->運算符用于通過指針來訪問結(jié)構(gòu)體的元素示例:structstStudentstStu;structstStudent*pstStu;pstStu=&stStu;printf("%s",pstStu->acName);structstStudent{characName[10]; intiNO;intiAge;};結(jié)構(gòu)體定義時不能定義自身結(jié)構(gòu)體變量,但可以定義自身的指針指針的指針voidmain(){ inti=6,*p,**dp; p=&i; dp=&p; printf(“%4d,%4d,%4d\n”,i,*p,**dp); printf(“%4x,%4x,%4x\n”,&i,p,*dp); printf(“%4x,%4x”,&p,dp);}一種變量專門用來存放指針變量的地址,這種變量我們稱之這指針的指針變量語法定義:type**name;示例:變量地址內(nèi)存值i0x10106………p0x24360x1010………dp0x33440x2436內(nèi)存示意圖函數(shù)指針函數(shù)在內(nèi)存中的物理位置-函數(shù)的入口點#include<stdio.h>intfun(inta,intb,int(*call)(int,int)){return(call(a,b));}intmain(){printf("max=%d\n",fun(1,2,max));printf("min=%d\n",fun(3,4,min));printf("sum=%d\n",fun(5,6,sum));return0;}指針數(shù)據(jù)類型小結(jié)定義含義int*p;p為指向整型數(shù)據(jù)的指針變量int*p[n];定義指針數(shù)組p,它有n個指向整型數(shù)據(jù)的指針元素int(*p)[n];p為指向含n個元素的一維數(shù)組的指針變量,行指針,數(shù)組指針int*p();p為帶回一個指針的函數(shù),該指針指向整型數(shù)據(jù),函數(shù)返回值指針int(*p)();p為指向函數(shù)的指針,該函數(shù)返回一個整型值,函數(shù)指針int**p;p是一個指針變量,它指向一個指向整型數(shù)據(jù)的指針變量,指針的指針無類型指針無類型指針可以指向任何類型的數(shù)據(jù)無類型指針定義:void*p;可以將任意類型的指針賦給無類型指針,但不能將無類型指針賦給其它類型指針,如: int*q,*m; p=q; /*允許賦值*/ m=(int*)p; 不能將無類型指針參與算術(shù)運算,如:p++;//錯誤,進行算法操作的指針必須是確定知道其指向的數(shù)據(jù)類型大小,將其改成:((int*)p)++;則能通過無類型指針主要作用對函數(shù)返回的限定(malloc函數(shù))對函數(shù)參數(shù)的限定(memcpy函數(shù))const限定符最低訪問原則——良好的程序設(shè)計風(fēng)格可用于不允許被修改的變量和形式參數(shù),保護實參 voidoutput(constdouble*pd) { printf(“%d”,*pd); /*允許*/ *pd=15.5; /*不允許!*/ }聲明const變量時需要初始化constintstuNum=100;指向常量數(shù)據(jù)的指針指針的值可以改變,無法通過指針修改指向的內(nèi)容關(guān)鍵字const放在指針類型前例如: inti,j,*q;

constint*p; /*等價于intconst*p;*/ p=&j; /*允許*/ p=&i; /*允許*/ i=10; /*允許*/ *p=5; /*不允許*/

指針常量指針常量又稱為常指針指針的值不能修改,指向的內(nèi)容可以修改關(guān)鍵字const放在“*”號和指針名之間例如:intvar1,var2;int*constp=&var1;*p=5; /*允許*/p=&var2; /*不允許*/指針與動態(tài)內(nèi)存分配1、靜態(tài)內(nèi)存分配

當程序中定義變量或數(shù)組以后,系統(tǒng)就會給變量或數(shù)組按照其數(shù)據(jù)類型及大小來分配相應(yīng)的內(nèi)存單元,這種內(nèi)存分配方式稱為靜態(tài)內(nèi)存分配。intk;//系統(tǒng)將給變量k分配4個字節(jié)的內(nèi)存單元charch[10];//系統(tǒng)將給這個數(shù)組ch分配10個字節(jié)的內(nèi)存塊,首地址就是ch的值靜態(tài)內(nèi)存分配一般是在已知道數(shù)據(jù)量大小的情況下使用

例如,要對10個學(xué)生的成績按降序輸出,則可定義一個數(shù)組:intscore[10];用于存放10個學(xué)生的成績,然后再進行排序。

如果事先并不知道學(xué)生的具體人數(shù),編寫程序時,人數(shù)由用戶輸入,然后再輸入學(xué)生的成績。那又如何如何處理呢?intn;intscore[n];scanf("%d",&n);如何解決?動態(tài)內(nèi)存分配指針與動態(tài)內(nèi)存分配2、動態(tài)內(nèi)存分配

所謂動態(tài)內(nèi)存分配是指在程序運行過程中,根據(jù)程序的實

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論