函數及變量的存儲_第1頁
函數及變量的存儲_第2頁
函數及變量的存儲_第3頁
函數及變量的存儲_第4頁
函數及變量的存儲_第5頁
已閱讀5頁,還剩69頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

函數及變量的存儲第一頁,共七十四頁,編輯于2023年,星期五目標描述C語言中的函數掌握C語言中常見的內置函數理解函數原型和函數的返回值熟練掌握自定義函數的定義和調用理解變量的作用域、生命期理解變量的存儲類型正確理解函數在C語言程序設計中的作用和地位;理解函數、形參、實參、作用域、生存期的概念;掌握各種函數的定義、原型聲明和調用的方法;理解全局變量、局部變量、靜態(tài)變量、靜態(tài)函數的作用域和生存期;掌握遞歸函數的編寫規(guī)則;掌握利用工程管理程序的方法;

第二頁,共七十四頁,編輯于2023年,星期五6.1.1什么是模塊化

模塊化程序設計方法:人們在求解某個復雜問題時,通常采用逐步分解、分而治之的方法,也就是將一個大問題分解成若干個比較容易求解的小問題,然后分別求解。程序員在設計一個復雜的應用程序時,往往也是把整個程序劃分成若干個功能較為單一的程序模塊,然后分別予以實現(xiàn),最后再把所有的程序模塊象搭積木一樣裝配起來,這種在程序設計中分而治之的策略,被稱為模塊化程序設計方法。6.1概述第三頁,共七十四頁,編輯于2023年,星期五maincabdefghijkl圖6-1C程序的模塊化C程序的模塊化第四頁,共七十四頁,編輯于2023年,星期五6.1.2什么是函數?在C語言中,模塊就是一組邏輯相關(這也體現(xiàn)了軟件工程中的“內聚性”)的語句的集合或說是用于完成特定任務的程序代碼的單元。根據規(guī)模的大小,C語言中的模塊有三種形式:語句塊(即復合語句)函數文件。函數是C語言中最為常用的模塊單元。因此通常說C程序是由函數組成的;函數是C語言程序的基本組成部分。第五頁,共七十四頁,編輯于2023年,星期五voidmain(){::::::x=x*x*x;y=y*y*y;z=z*z*z;ans1=x+y+z;

a=a*a*a;b=b*b*b;c=c*c*c;ans2=a+b+c;:::::}重復多次的同一計算類型voidmain(){::::::ans1=cube(x,y,z);ans2=cube(a,b,c);:::::}intcube(inta,b,c){intans;ans=(a*a*a)+(b*b*b)+(c*c*c);returnans;}函數主程序ans函數可以把相對獨立的某個功能抽象出來,使之成為程序中的一個獨立實體。可以在同一個程序或其他程序中多次重復使用為什么使用函數?第六頁,共七十四頁,編輯于2023年,星期五使程序變得更簡短而清晰有利于程序維護可以提高程序開發(fā)的效率提高了代碼的重用性函數機制的優(yōu)點第七頁,共七十四頁,編輯于2023年,星期五6.2.1

函數的分類內置函數(庫函數):由C語言系統(tǒng)提供;用戶無須定義,也不必在程序中作類型說明;只需在程序前包含有該函數定義的頭文件;自定義函數:用戶在程序中根據需要而編寫的函數;從用戶角度6.2函數的定義與使用第八頁,共七十四頁,編輯于2023年,星期五內置函數頭文件用途doublesqrt(doublex)math.h計算x的平方根doublepow(doublex,doubley)計算x的y次冪doubleceil(doublex)求不小于x的最小整數,并以double形式顯示doublefloor(doublex)求不大于x的最大整數,并以double形式顯示inttoupper(intx)ctype.h如果x為小寫字母,則返回對應的大寫字母inttolower(intx)如果x為大寫字母,則返回對應的小寫字母intrand(void)stdlib.h產生一個隨機數voidexit(intretval)終止程序常用庫函數使用庫函數的一般方法:1、函數功能2、函數參數的數目和順序,及各參數意義和類型3、函數返回值意義和類型4、需要使用的包含文件第九頁,共七十四頁,編輯于2023年,星期五函數定義格式函數體合法標識符函數返回值類型函數類型函數名(形參類型說明表){

說明部分

語句部分

return語句}以下紅色的為函數的6個元素函數頭部第十頁,共七十四頁,編輯于2023年,星期五參數:一般用于一個函數把數據傳遞給另一個函數(調用者和被調用者之間),實現(xiàn)函數之間的通信。定義函數的時候,函數的參數是形式參數,是對一件具體事件可能需要數據的假設。返回值:即函數帶回來的值。而返回值的類型是在定義函數的時指定的,即用“返回值類型”指定函數的類型。1、如果類型標識符為void則表示不需要帶回函數值;2、如果沒有類型標識,則TC2.0默認返回值類型是int(在vc++6.0中則認為默認為void,視編譯器的不同而不同)。函數體:一對花括號里面的內容(包括聲明部分和語句部分)又被稱為函數體,當函數體為空的時候,該函數也被叫做空函數,就是說它什么也不做。第十一頁,共七十四頁,編輯于2023年,星期五例6-1計算兩個整數的平均數的函數。/*

函數功能:就算平均數函數入口參數:整型x,存儲第一個運算數整型y,存儲第二個運算數函數返回值:平均數*/intAverage(intx,inty){intresult;result=(x+y)/2;returnresult;}第十二頁,共七十四頁,編輯于2023年,星期五

大多數情況下,調用者(主調函數)和被調用者(被調用函數)之間有數據傳遞關系,也就是說該函數有參數(可以稱為有參函數,否則叫做無參函數)。在定義函數時函數名后面括號中的參數稱為“形式參數”(簡稱“形參”),在主調函數中調用一個函數時,函數名后面括號中的參數(可以是一個“表達式”)稱為“實際參數”(簡稱“實參”)。參數和參數傳遞的方式6.2.3函數的參數和返回值第十三頁,共七十四頁,編輯于2023年,星期五例6-2調用函數時的數據(參數)傳遞。#include<stdio.h>voidmain(){intmax(intx,inty);inta,b,c;scanf("%d,%d",&a,&b);c=max(a,b);printf("maxis%d",c);}intmax(int

x,inty)/*定義有參函數max*/{intz;z=x>y?x:y;return(z);}運行情況如下:7,8↙Maxis8第十四頁,共七十四頁,編輯于2023年,星期五關于形參和實參的說明:在定義函數中指定的形參,在函數尚未被調用時,它們并不占用內存中的存儲單元。只有在發(fā)生函數調用時,函數max中的形參才被分配內存單元。在調用結束后,形參所占的內存單元也被釋放。實參可以是常量、變量或表達式,例如:max(3,a+b);但要求它們有確定的值。在調用時將實參的值賦給形參。參數和參數傳遞的方式第十五頁,共七十四頁,編輯于2023年,星期五關于形參和實參的說明:在被定義的函數中,必須指定形參的類型。實參與形參的類型應相同或賦值兼容。在C語言中,實參向形參的數據傳遞是“值傳遞”,單向傳遞,只由實參傳給形參,而不能由形參傳回來給實參。在內存中,實參單元與形參單元是不同的單元。參數和參數傳遞的方式第十六頁,共七十四頁,編輯于2023年,星期五2222abxy圖6-3參數值傳遞221015abxy圖6-4實參值不變參數和參數傳遞的方式第十七頁,共七十四頁,編輯于2023年,星期五int

Check(intnum){if(num%5==0)return1;elsereturn0;}通常,希望通過函數調用使主調函數能得到一個確定的值,這就是函數的返回值,也稱函數值。C語言中的return語句用于向調用函數返回值,語法如下:return(<表達式>);函數的返回值第十八頁,共七十四頁,編輯于2023年,星期五voidswap(intx,inty){intz;z=x;x=y;y=z; printf("\nx=%d,y=%d",x,y);}main(){inta=10,b=20;swap(a,b);printf("\na=%d,b=%d\n",a,b);}程序輸出結果:x=20,y=10a=10,b=20形式參數(形參)實際參數(實參)【例】編一程序,將主函數中的兩個變量的值傳遞給swap函數中的兩個形參,交換兩個形參的值。單向值傳遞第十九頁,共七十四頁,編輯于2023年,星期五c=max(a,b);(調用main函數)(max函數)intmax(intx,inty){intz;z=x>y?x:y;return(z);}圖6-2函數調用函數的返回值第二十頁,共七十四頁,編輯于2023年,星期五voidmain(){::::::ans1=cube(2,5,7);ans2=cube(2,3,4);:::::}intcube(inta,intb,intc){intans;ans=(a*a*a)+(b*b*b)+(c*c*c);returnans;}函數主程序ans參數(實參)參數(形參)返回值第二十一頁,共七十四頁,編輯于2023年,星期五(1)函數的返回值是通過函數中的return語句獲得的。說明return語句將被調用函數中的一個確定值帶回主調函數中去。如果需要從被調用函數帶回一個數值,則被調用函數中必須包含reutrn語句。如果不需要則可以不要return語句。一個函數中可以有一個以上的return語句,執(zhí)行到哪一個return語句,則哪個語句起作用。return語句后面的括號也可以不要,如“returnz;”和“return(z);”等價。return后面的值可以是一個表達式。例如,例6.2中的函數max可以改寫如下:max(intx,inty){return(x>y?x:y);}第二十二頁,共七十四頁,編輯于2023年,星期五(2)函數的類型。既然函數有返回值,這個值當然應屬于某一個確定的類型,應當在定義函數時指定函數值的類型。例如下面是3個函數的首行:

intmax(floatx,floaty) /*函數值為整型*/

charletter(charc1,charc2))/*函數值為字符型*/

doublemin(intx,inty)) /*函數值為雙精度型*/在C語言中,凡不加類型說明的函數,自動按整型處理。第二十三頁,共七十四頁,編輯于2023年,星期五(3)在定義函數時指定的函數類型一般應該和return語句中的表達式類型一致。例6.2中指定max函數值為整型,而變量z也被指定為整型,通過return語句把z的值作為max的函數值,由max帶回主調函數。z的類型與max函數的類型是一致的,是正確的。如果函數值的類型和return語句中表達式的值不一致,則以函數類型為準。對數值型數據,可以自動進行類型轉換。即函數類型決定返回值的類型。(4)對于不帶返回值的函數,應當用“void”定義函數為“無類型”(或稱“空類型”)。

這樣,系統(tǒng)就保證不使函數帶回任何值,即禁止在調用函數中使用被調用函數的返回值。此時在函數體中不得出現(xiàn)return語句。第二十四頁,共七十四頁,編輯于2023年,星期五例6-3返回值類型與函數類型不同。#include<stdio.h>voidmain(){intmax(intx,inty);floata,bintc;scanf("%f,%f",&a,&b);c=max(a,b);printf("maxis%d",c);}intmax(floatx,floaty){floatz; /*z為實型變量*/z=x>y?x:y;return(z);}運行情況如下:1.5,2.5Maxis2第二十五頁,共七十四頁,編輯于2023年,星期五6.3.1函數調用的一般形式函數調用的一般形式為

函數名(實參表列);注意事項:(1)如果是調用無參函數,則“實參表列”可以沒有,但是括號不能省略。(2)如果實參表列包含多個實參,則各個參數間用逗號隔開。實參可以是常量、變量、表達式、函數等6.3函數調用

第二十六頁,共七十四頁,編輯于2023年,星期五注意事項:

(3)賦值對應關系:

實參1->形參1

實參2->形參2

……

實參n->形參n(4)實參表求值順序(即實參賦值給形參的順序)因系統(tǒng)而定。TC、BC、VC均是自右向左,也就是說最右邊的實參最先賦值給最右邊的形參,最左邊的實參最后賦值給最左邊的形參。但VC與TC、BC在具體賦值時稍有不同,注意它們之間的區(qū)別。第二十七頁,共七十四頁,編輯于2023年,星期五例6-4實參求值的順序。#include<stdio.h>voidmain(){intf(inta,intb);/*函數聲明*/inti=2,p;p=f(i,++i);/*函數調用*/printf("%d\n",p);}intf(inta,intb)/*函數定義*/{intc;if(a>b)c=1;elseif(a==b)c=0;elsec=-1;return(c);}問:在TurboC2.0和TurboC++3.0系統(tǒng)上運行的結果?原型聲明

i為實參

a、b為形參

第二十八頁,共七十四頁,編輯于2023年,星期五若按自左至右順序求實參的值,則函數調用相當于f(2,3),程序運行應得結果為“-1”。若按自右至左順序求實參的值,則它相當于f(3,3),程序運行結果為“0”。分析:

如果本意是按自左而右順序求實參的值,即f(2,3)調用,可改寫成:

j=i;k=++i;p=f(j,k);

如果本意是自右而左求實參的值,即f(3,3)調用,可改寫成:

j=++i;p=f(j,j);是否有辦法讓參數確定?第二十九頁,共七十四頁,編輯于2023年,星期五1.函數語句把函數調用作為一個語句。這時不要求函數帶來返回值,只要求函數完成一定的操作。例如:

printstar();printf(“Hello,World!\n”);2.函數表達式函數出現(xiàn)在一個表達式中,這種表達式稱為函數表達式。這是要求函數帶回一個確定的值以確定參加表達式的運算。例如:

C=2*max(a,b);

函數max是表達式的一部分,它的值乘2再賦給c。6.3.2函數調用的方式按函數在程序中出現(xiàn)的位置分,可有3種函數調用的方式:第三十頁,共七十四頁,編輯于2023年,星期五3.函數參數函數調用作為一個函數的實參。例如:

M=max(a,max(b,c));

其中max(b,c)是一次函數調用,它的值作為max另一次調用的實參。M的值是a、b、c三者中的最大者。例如:

printf(“%d”,max(a,b));

也是把max(a,b)作為printf函數的一個函數。函數調用作為函數的參數,實質上也是函數表達式形式調用的一種,因為函數的參數本來就要求是表達式形式。第三十一頁,共七十四頁,編輯于2023年,星期五6.3.3對被調用函數的聲明和函數原型#include<stdio.h>floatcount(int,int);voidmain(){......}floatcount(intx,inty){...}函數原型說明在形式上與函數頭部類似,最后加一個分號。原型說明中參數表里的參數名可以不寫(只寫參數類型)。第三十二頁,共七十四頁,編輯于2023年,星期五問題描述:根據用戶的選擇求不同形狀的面積。函數調用示例#include<stdio.h>voidAreaOfRect();voidAreaOfTriangle();voidAreaOfRound();voidmain(){intselect;do{ printf("0、退出\n1、長方形\n2、三角形\n3、圓形\n"); printf("請選擇功能:"); scanf("%d",&select); if(select==0)break; switch(select){ case1:AreaOfRect();break;//長方形

case2:AreaOfTriangle();break;//三角形

case3:AreaOfRound();break;//圓形

default:printf("輸入有誤,請在0~4之間選擇。\n"); }}while(1);}voidAreaOfRect(){intx,y;printf("請輸入長方形的長:");scanf("%d",&x);printf("請輸入長方形的寬:");scanf("%d",&y);printf("面積為:%d\n",(x*y));}voidAreaOfTriangle(){intx,y;printf("請輸入三角形的底:");scanf("%d",&x);printf("請輸入三角形的高:");scanf("%d",&y);printf("面積為:%d\n",(x*y)/2);}voidAreaOfRound(){intr;printf("請輸入圓形的半徑:");scanf("%d",&r);printf("面積為:%d\n",3.14*r*r);}函數原型第三十三頁,共七十四頁,編輯于2023年,星期五在一個函數中調用另一個函數(即被調用函數)需要具備的條件如下:首先被調用的函數必須是已經存在的函數(庫函數或自定義函數)。如果使用庫函數,還應該在文本開頭用#include命令將調用有關庫函數時所需用到的信息(這些信息是一些常量和函數原型)“包含”到本文件中來,否則函數將不能正常地得到調用。例如,前面經常用到過:#include<stdio.h>3.如果使用用戶自定義的函數,則如果該函數被定義的位置在調用它的函數(即主調函數)的后面(在同一文件中),應該在主調函數中對被調函數作聲明。如果被調用函數的定義出現(xiàn)在主調函數之前,可以不必加以聲明。第三十四頁,共七十四頁,編輯于2023年,星期五對于函數的位置:對于非int函數,調用單位的位置要在被調用單位在下面,否則編譯產生錯誤。解決方法是:在調用單位加上被調用函數的聲(說)明。voidf(){…}main(){…f();

…}voidf(){…}main(){…f();

…}voidf(){…}main(){voidf();…f();…}第三十五頁,共七十四頁,編輯于2023年,星期五例6-5編制子函數實現(xiàn)求兩個單精度實數的和,main函數調用該函數的時候要先聲明。/*6_5.c*/#include<stdio.h>voidmain(){floatadd(floatx,floaty);/*對被調用函數add的聲明*/floata,b,c;scanf("%f,%f",&a,&b);

c=add(a,b);printf("sumis%f\n",c);}floatadd(floatx,floaty)/*函數首部*/{floatz;/*函數體*/z=x+y;return(z);}運行情況如下:3.6,6.5↙sumis10.100000floatadd(float,float);第三十六頁,共七十四頁,編輯于2023年,星期五綜上所述,函數原型的一般形式有兩種:(1)函數類型函數名(參數類型1,參數類型2,…,參數類型n);(2)函數類型函數名(參數類型1參數名1,參數類型2參數名2,…參數類型n參數名n);第三十七頁,共七十四頁,編輯于2023年,星期五應該注意到函數的原型與函數的定義是不一樣的。函數的定義是指對函數功能的確立,包括指定函數名、函數值類型、形參及其類型、函數體等,它是一個完整的、獨立的函數單位。函數的聲明的作用則是把函數的名字、函數類型以及形參的類型、個數和順序通知編譯系統(tǒng),以便在調用該函數時系統(tǒng)按此進行對照檢查(例如,函數名是否正確,實參與形參的類型和個數是否一致等)。第三十八頁,共七十四頁,編輯于2023年,星期五6.3.4嵌套調用在C語言中,函數的定義是平行的,不允許進行函數的嵌套定義,即在一個函數體中不允許定義另一個函數。而函數之間的調用可以是任意的,即允許在一個函數體內再調用其他函數,在函數體中再調用其它函數稱為函數的嵌套調用。第三十九頁,共七十四頁,編輯于2023年,星期五voidreverse(){::::::::::::::::::::}#include<stdio.h>voidmain(){ :::::::::

palindrome(); :::::::: ::::::::}voidpalindrome(){

::::::::reverse();::::::::}從一個函數調用另一個函數稱為函數的嵌套調用

例如:C規(guī)定:函數定義不可嵌套,但可以嵌套調用函數第四十頁,共七十四頁,編輯于2023年,星期五例6-6函數的嵌套調用。main(){

aia();}aia(){ber();}ber(){cal();}cal(){…..}圖6-5函數的嵌套調用89246135710

函數main調用了aia,aia調用了ber,ber又調用了cal。其調用過程和返回過程如圖所示。voidaia(),ber(),cal();main(){printf("I'minmain.\n");

aia();}voidaia(){printf("NowI'minaia.\n");

ber();}voidber(){printf("NowI'minber.\n");

cal();}voidcal(){printf("NowI'mincal.");}第四十一頁,共七十四頁,編輯于2023年,星期五一個函數直接或間接地調用函數本身,這種調用稱為遞歸調用,前者稱為直接遞歸,后者稱為間接遞歸。遞歸調用的函數稱為遞歸函數。由于遞歸非常符合人們的思維習慣,而且許多數學函數及許多算法或數據結構都是遞歸定義的,因此,遞歸調用頗具實用價值。6.3.4函數遞歸調用第四十二頁,共七十四頁,編輯于2023年,星期五/*此函數用于計算n的階乘*/intfactorial(intn)

{inta;if(n==1)return1;else{a=n*factorial(n-1);returna;}}在一個函數體內調用自身稱為函數的遞歸調用

第四十三頁,共七十四頁,編輯于2023年,星期五例6-7利用函數的遞歸調用來求n的階乘。#include<stdio.h>longfact();/*聲明被調用函數返回值為長整型*/main()/*主函數*/{inth,i;printf("請輸入任一正整數:\n");scanf("%d",&h);for(i=0;i<=h;++i)printf("%d!=%ld\n",i,fact(i));}longfact(intn)/*求階乘函數*/{longintres;if(n==0)res=1;elseres=n*fact(n-1);/*遞歸調用*/return(res);}請輸入任一正整數:6↙0!等于11!等于12!等于23!等于64!等于245!等于1206!等于720程序執(zhí)行后顯示:第四十四頁,共七十四頁,編輯于2023年,星期五6.3.6程序設計舉例(使用函數編寫程序)例6-8

輸出5之內的數字金字塔。例6-9輸入精度e,使用格里高利公式求π的近似值,精確到最后一項的絕對值小于e。要求定義和調用函數funpi(e)求π的近似值。例6-10采用遞歸方式實現(xiàn)二分查找。二分查找算法是對有序數列進行查找操作的一種有效操作。實際上,這種查找方法是一個遞歸的過程。第四十五頁,共七十四頁,編輯于2023年,星期五結構體變量作為函數參數140頁例5-3將鍵盤輸入的有關學生的檔案信息用函數list實現(xiàn)。#include<stdio.h>structSTUD{charname[20];longnum;intage;charsex;floatscore;};voidlist(structSTUDstud){printf("%-20s%-10ld%-4d%-4c%-6.2f\n",,stud.num,stud.age, stud.sex,stud.score);}voidmain(){structSTUDstud[3];inti;for(i=0;i<3;i++){printf("InputallinformationabouttheNo.%dstudent:\n",i+1);getchar();gets(stud[i].name);scanf("%ld,%d,%c,%f",&stud[i].num,&stud[i].age,&stud[i].sex,&stud[i].score);}printf("\n%-20s%-10s%-4s%-4s%-6s\n","Name","Num","Age","Sex","Scores");for(i=0;i<3;i++)list(stud[i]);}第四十六頁,共七十四頁,編輯于2023年,星期五返回結構體類型值的函數例5-4第四十七頁,共七十四頁,編輯于2023年,星期五總結函數是程序中的一個相對獨立的單元或模塊,程序在需要時可以任意多次地調用函數來完成特定功能使用函數帶來的好處:程序更清晰、易維護、分模塊方便設計與開發(fā)、提高代碼的重用性C語言提供了極為豐富的內置函數,這些內置函數分門別類地放在不同的頭文件中,要使用這些內置函數,只要在程序前包含相應的頭文件即可第四十八頁,共七十四頁,編輯于2023年,星期五總結自定義函數是用戶在程序中根據需要而編寫的函數函數的結構包括:返回值類型、函數名、參數列表、函數體函數原型說明以便向編譯器指出該函數使用什么樣的格式和語法函數調用時程序控制流將轉向被調函數,被調函數執(zhí)行結束時,控制流返回主調函數return語句用于向調用函數返回值第四十九頁,共七十四頁,編輯于2023年,星期五6.5變量的性質在C程序世界里,程序由一個個函數組成,這些函數是相對獨立的模塊,為了使得各個函數能彼此協(xié)作以完成一個程序任務,各個函數之間需要通信和協(xié)作,而函數之間通信所采用的媒介就是函數中的數據,也就是變量。于是對于變量來說就有兩個值得考慮的問題了:變量是否可以被訪問,也就是變量在什么范圍中有效(可見性,作用域)。變量占據的內存單元什么時候開辟,什么時候被釋放(存在性,生命期)。第五十頁,共七十四頁,編輯于2023年,星期五6.6變量的作用域與生命期限于陸地限于海洋限于空中第五十一頁,共七十四頁,編輯于2023年,星期五作用域和生存期的基本概念變量的作用域即變量的作用范圍(或有效范圍)。表現(xiàn)為有的變量可以在整個程序或其它程序中進行引用,有的則只能在局部范圍內引用。其作用域范圍可分為兩種:即局部變量和全局變量

變量的生存期變量從被生成到被撤消的這段時間。實際上就是變量占用內存的時間。

按其生存期可分為兩種:即動態(tài)變量和靜態(tài)變量

變量只能在其生存期內被引用。作用域和生存期是從空間和時間的角度來體現(xiàn)變量的特性。

第五十二頁,共七十四頁,編輯于2023年,星期五6.6.2局部變量作用域和生存期定義在函數內作定義說明的變量,也稱為內部變量

。

作用域僅限于函數內,離開函數后不可再引用。

生存期從函數被調用的時刻到函數返回調用處的時刻(靜態(tài)局部變量除外)。intf1(intx,inty){intz;z=x>y?x:y;return(z);}voidf2(){printf("%d\n",z);}局部變量

變量x、y、z的作用域引用錯誤!第五十三頁,共七十四頁,編輯于2023年,星期五

說明

(1)主函數main()中定義的變量也是局部變量,它只能在主函數中使用,其它函數不能使用。同時,主函數中也不能使用其它函數中定義的局部變量。

intf3(intx);voidmain(){inta=2,b;b=a+y;printf("%d\n",b);}intf3(intx

){inty;y=a+5;return(y);}局部變量

變量a、b的作用域變量x、y的作用域局部變量

錯誤!錯誤!第五十四頁,共七十四頁,編輯于2023年,星期五

說明

(2)形參變量屬于被調用函數的局部變量;實參變量則屬于全局變量或調用函數的局部變量。

(3)允許在不同的函數中使用相同的變量名,它們代表不同的對象,分配不同的單元,互不干擾,也不會發(fā)生混淆。#include<stdio.h>voidsubf();voidmain(){

inta,b;

a=3,b=4;printf("main:a=%d,b=%d\n",a,b);subf();printf("main:a=%d,b=%d\n",a,b);}voidsubf(){inta,b;a=6,b=7;printf("subf:a=%d,b=%d\n",a,b);}運行結果:main:a=3,b=4subf:a=6,b=7main:a=3,b=4變量名相同

第五十五頁,共七十四頁,編輯于2023年,星期五

說明

(4)在復合語句中定義的變量也是局部變量,其作用域只在復合語句范圍內。其生存期是從復合語句被執(zhí)行的時刻到復合語句執(zhí)行完畢的時刻。#include<stdio.h>voidmain(){

inta=2,b=4;

{intk,b;k=a+5;b=a*5;printf("k=%d\n",k);printf("b=%d\n",b);}printf("b=%d\n",b);a=k+2;}main中的局部變量

復合語句中的局部變量

mian中變量a、b的作用域

復合語句中變量k、b的作用域輸出k=7

輸出b=10

輸出b=4

錯誤!第五十六頁,共七十四頁,編輯于2023年,星期五6.6.2全局變量作用域和生存期定義在函數外部作定義說明的變量,也稱為外部變量

。它不屬于哪一個函數,而屬于一個源程序文件。

作用域從定義變量的位置開始到本源文件結束,及有extern說明的其它源文件。

生存期與程序相同。即從程序開始執(zhí)行到程序終止的這段時間內,全局變量都有效。

#include<stdio.h>#include<math.h>intsign();//計算數n的平方根floatsqr(){if(n>0)return(sqrt(n));elsereturn(-1);}floatn=0;voidmain(){ints;floatt;scanf("%f",&n);s=sign();//取符號

t=sqr();//取平方根

printf("s=%dt=%f",s,t);}//取數n的符號intsign(){intr=0;if(n>0)r=1;if(n<0)r=-1;return(r);}定義全局變量,并賦初值局部變量全局變量n的作用域

局部變量s、t的作用域局部變量局部變量r的作用域錯誤!第五十七頁,共七十四頁,編輯于2023年,星期五

說明

(1)應盡量少使用全局變量。全局變量在程序全部執(zhí)行過程中始終占用存儲單元降低了函數的獨立性、通用性、可靠性及可移植性降低程序清晰性,容易出錯

(2)若外部變量與局部變量同名,則外部變量被屏蔽。要引用全局變量,則必須在變量名前家上兩個冒號“::”

#include<stdio.h>inta=10;

//全局變量voidmain(){

inta=100;

//局部變量(與全局變量同名)

printf("locala=%d\n",a);printf("globala=%d\n",::a);}運行結果:locala=100globala=10注意:局部變量與全局變量同名極易導致程序員犯邏輯錯誤。第五十八頁,共七十四頁,編輯于2023年,星期五#include<stdio.h>inta=3,b=5;max(inta,intb){ intc; c=a>b?a:b; return(c);}main(){ inta=8; printf("%d\n",max(a,b));}運行結果?第五十九頁,共七十四頁,編輯于2023年,星期五

說明

(3)全局變量定義必須在所有的函數之外,且只能定義一次,并可賦初始值。全局變量定義的一般形式為:[extern]類型說明符全局變量名1[=初始值1],……,全局變量名n[=初始值n];可缺?。harch='Y';voidmain(){……}charch;voidfunc(){……}定義全局變量ch錯誤!ch只能定義一次例:inta=2,b=4;externinta=2,b=4;第六十頁,共七十四頁,編輯于2023年,星期五

說明

(4)對全局變量進行說明,可擴展全局變量的作用域。全局變量說明的一般形式為:extern

類型說明符全局變量名1,…,全局變量名n;不可缺??!不可賦初值!voidgx(),gy();voidmain(){externintx,y;printf("1:x=%d\ty=%d\n",x,y);y=246;gx();gy();}externintx,y;voidgx(){x=135;printf("2:x=%d\ty=%d\n",x,y);}intx=0,y=0;voidgy(){printf("3:x=%d\ty=%d\n",x,y);}全局變量定義未說明前的作用域全局變量說明說明后的作用域全局變量說明說明后的作用域運行結果:

1:x=0y=02:x=135y=2463:x=135y=246第六十一頁,共七十四頁,編輯于2023年,星期五

說明

(5)全局變量定義與全局變量的說明的區(qū)分

externinta;

voidfunc1(){……//引用變量a}externinta=2;

voidfunc2(){……//引用變量a}誰是定義?誰是說明?全局變量定義(因為賦了初值)全局變量說明

注意:兩者中有且只能有一個對變量a賦初始值,不能都對變量a賦初始值或都不賦值,否則編譯錯!

第六十二頁,共七十四頁,編輯于2023年,星期五6.7變量的生命期<--變量的存儲類型

概述變量的屬性①數據類型:變量所持有數據的性質(操作屬性)。規(guī)定了它們的取值范圍和可參與的運算。

②存儲類型:

規(guī)定了變量占用內存空間的方式,也稱為存儲方式。

存儲類型:寄存器、靜態(tài)存儲區(qū)、動態(tài)存儲區(qū)

auto---------自動型

register-----寄存器型

static-------靜態(tài)型

extern-------外部型動態(tài)存儲區(qū)靜態(tài)存儲區(qū)存儲類型說明符數據類型說明符變量名1,變量名2,…,變量名n;變量定義的完整形式應為:

第六十三頁,共七十四頁,編輯于2023年,星期五1、動態(tài)變量(auto型變量)[auto]數據類型說明符變量名1,變量名2,…,變量名n;

定義格式說明存儲類型說明符auto可以省略。動態(tài)變量只能在函數內或復合語句中定義,它屬于局部變量(動態(tài)局部變量)。voidfunc(){

inti,j,k;

……}等價于autointi,j,k;autointk;

voidfunc(){……}錯誤!動態(tài)變量不可定義在函數外

第六十四頁,共七十四頁,編輯于2023年,星期五2、靜態(tài)變量(static型變量)靜態(tài)變量的類型說明符是static。靜態(tài)變量屬于靜態(tài)存儲類型。靜態(tài)局部變量在局部變量的說明前加上static就構成靜態(tài)局部變量

例如:

staticinta,b;staticfloatarray[5]={1,2,3,4,5};第六十五頁,共七十四頁,編輯于2023年,星期五靜態(tài)局部變量與動態(tài)變量之比較靜態(tài)局部變量與動態(tài)變量均屬于局部變量靜態(tài)局部變量生存期長,為整個源程序。動態(tài)變量生存期短靜態(tài)局部變量的生存期雖然為整個源程序,但是其作用域仍與動態(tài)變量相同voidfunc();voidmain()

{inta;a=s+5;……}voidfunc(){staticints;……}定義靜態(tài)局部變量s錯誤!s的作用域第六十六頁,共七十四頁,編輯于2023年,星期五靜態(tài)局部變量與動態(tài)變量之比較靜態(tài)局部變量若在定義時未賦初值,則系統(tǒng)自動賦初值0

靜態(tài)局部變量賦初值只一次,而動態(tài)變量賦初值可能多次#include<stdio.h>voidmain(){inti;voidfunc();//函數說明

for(i=1;i<=5;i++)func();//函數調用}voidfunc()//函數定義{

autointj=0;++j;printf("%d",j);}#include<stdio.h>voidmain(){inti;voidfunc();//函數說明

for(i=1;i<=5;i++)func();//函數調用}voidfunc()//函數定義{

staticintj=0;++j;printf("%d",j);}動態(tài)變量靜態(tài)變量運行結果:11111

運行結果:12345

第六十七頁,共七十四頁,編輯于2023年,星期五

溫馨提示

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

評論

0/150

提交評論