第4章-單片機的C51程序設計_第1頁
第4章-單片機的C51程序設計_第2頁
第4章-單片機的C51程序設計_第3頁
第4章-單片機的C51程序設計_第4頁
第4章-單片機的C51程序設計_第5頁
已閱讀5頁,還剩115頁未讀 繼續免費閱讀

下載本文檔

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

文檔簡介

第4章單片機的C51程序設計

吳政江制作

貴州電子信息職業技術學院貴州省人才培養優秀單位4.1C51程序的結構特點4.2C51語法基礎4.3C51的數據類型、存儲類型及常量與變量4.4C51對單片機主要資源的定義4.5C51的基本運算4.6C51的構造數據類型4.7C51的流程構造語句4.8C51的函數4.9指針4.10C51程序設計舉例實訓四:單片機控制流水燈(C51程序)實訓五:計數器的C51程序設計與制作小結習題與思考題4.1C51程序的結構特點

4.1.1C語言與匯編語言的比較單片機的C51編程與匯編語言編程相比,具有以下優點。(1)對單片機的指令系統不要求有任何的了解,就可以用C語言直接編程操作單片機。(2)寄存器分配、不同存儲器的尋址以及數據類型等細節完全由編譯器自動管理。(3)程序有規范的結構,可分成不同的函數,可使程序結構化。(4)庫中包含許多標準函數,具有較強的數據處理能力,使用十分方便。(5)具有方便的模塊化編程技術,使已編好的程序很容易移植。4.1.2C51程序的結構特點

舉例:設單片機AT89C51的P1.0口接有一個發光二極管,如圖4-1所示。試用C51編程使該發光二極管間隔1s亮滅閃動。LEDVccAT89C51P1.0R1圖4-1驅動發光二極管#include<reg51.h>//包含51系列單片機頭文件#defineuintunsignedint//宏定義sbitled1=P1^0;//聲明單片機P1口的第一位voiddelayms(uint);//聲明延時子函數voidmain()//主函數{While(1)//大循環{led1=0;/*點亮接在P1.0引腳上的LED*/delayms(1000);//延時1秒led1=1;/*關閉接在P1.0引腳上的LED*/delayms(1000);//延時1秒}}voiddelayms(uintxms)//延時x毫秒子函數{uinti,j;for(i=xms;i>0;i--)/*i=xms即延時約xms毫秒*/for(j=110;j>;j--);}由以上例子可看出C51程序結構具有以下特點:(1)C語言程序是由函數構成的。(2)一個函數由兩部份組成。①函數首部,即函數的第一行。②函數體,即函數首部下面的大括號“{}”內的部分。函數體一般包括:a.聲明部分:在這部分中定義所用到的變量,如“sbitled1=P1^0;”。b.執行部分:由若干個語句組成。(3)一個C語言程序,總是從main()函數開始執行的,而不管物理位置上這個main()放在什么地方。(4)C語言源程序的前面幾行通常是以“#”開頭的預處理命令。預處理命令包括文件包含(include)命令、宏(define)命令以及條件編譯命令等。(5)C語言區分大小寫。如將“include”寫成“INCLUDE”就會編譯出錯。(6)C語言書寫的格式自由,可以在一行寫多個語句,也可以把一個語句寫在多行。(7)每個語句和資料定義的最后必須有一個分號“;”,分號“;”是C語句的必要組成部分,即語句結束標志。但預處理命令、函數頭和花括號“}”之后不能加分號“;”。(8)可以用/*……*/的形式為C程序的任何一部分作注釋。C51也支持C++風格的注釋,即用“//”引導的后面的語句是注釋。例如:P1_0=!P1_0;//取反P1.0這種風格的注釋,只對本行有效,所以不會出現上面的問題,而且書寫也比較方便。因此,程序在只需要一行注釋的時候,建議采用這種格式。(9)一個C語言源程序可以由一個或多個源文件組成。4.2C51語法基礎

4.2.1C語言詞匯(1)標識符在程序中使用的變量名、函數名、標號等統稱為標識符。C語言規定,標識符只能是字母(A~Z,a~z)、數字(0~9)、下劃線(_)組成的字符串,并且第一個字符必須是字母或下劃線。①標準C語言不限制標識符的長度,但它受各種版本的C語言編譯系統限制,同時也受到具體機器的限制。②在標識符中,大小寫是有區別的。③標識符雖然可由程序員隨意定義,但標識符是用于標識某個量的符號。④標識符不能使用系統保留的關鍵字。(2)關鍵字(也叫保留字)①數據類型關鍵字。用于定義或說明變量、函數或其他數據結構的類型。主要有char,double,float,int,long,short,signed,struct,union,unsigned,void,enum等12個。②控制語句關鍵字。用于表示一個語句的功能。主要有break,case,continue,default,do,else,for,goto,if,return,switch,while等12個。③存儲類型關鍵字。用于說明變量或函數的存儲類型。主要有auto,extern,register,static等4個。④預處理命令關鍵字。用于表示一個處理命令。主要有include、define等2個。⑤其他關鍵字。主要有const,sizeof,typedef,volatile等4個。(3)運算符C語言中含有相當豐富的運算符。如強制類型轉換運算符、算術運算符、關系運算符、邏輯運算符以及位運算符等。運算符與變量、函數一起組成表達式,表示各種運算功能。運算符由一個或多個字符組成。(4)分隔符①逗號分隔符。

②空格分隔符。4.2.2編譯預處理

編譯預處理命令概念:計算機將C語言編譯為機器語言時進行的預處理。這些命令只在編譯時有效,不是計算機運行的可執行語句。編譯預處理命令以“#”開頭,末尾不加分號,包括頭宏命令、文件包含命令、條件編譯命令等。

(1)宏命令作用:用標識符來代表一個字符串,系統在編譯之前自動將標識符替換為字符串。主要用于定義常量。宏定義的標識符(常量)一般用大寫字母,以便與變量相區別。定義形式:#define標識符字符串例如:#definePI3.14/*后續程序中所有的PI都用3.14代替。即凡是出現PI的地方即表示3.14,這樣做有利于閱讀程序和修改程序。*/(2)文件包含

文件包含:指在一個文件中將另一個文件的全部內容包含進來,通常用來將程序中用到的系統函數、宏標識符、自定義函數等的文件包含進來。被包含的文件也叫頭文件(以“.h”為擴展名的文件)。

格式:#include<文件名>或#include“文件名”在KeilC51中常用的包含文件(頭文件)有以下三種:

①reg51.h頭文件。reg51.h是對51子系列單片機的特殊功能寄存器進行定義的頭文件,使用匯編語言中的特殊功能寄存器名稱,將各個特殊功能寄存器定義為該寄存器的直接地址,在C語言中可以通過寄存器名稱直接對這些寄存器進行操作,特殊功能寄存器名稱全部使用大寫。reg51.h沒有對單片機的四個輸入輸出端口進行位定義,如果程序中需要對并行端口進行位操作,可以使用regx51.h。對于52系列單片機,相應的頭文件為reg52.h或regx52.h。②stdio.h頭文件。stdio.h是標準輸入輸出庫函數頭文件。該庫函數文件是定義計算機鍵盤輸入與計算機屏幕顯示的庫函數,單片機本身無需這些庫函數,但為了方便利用計算機調試程序,需要包含該頭文件。常用的標準輸入、輸出庫函數有以下兩種:a.printf(格式控制,輸出列表);。該函數按指定格式在屏幕上顯示對應輸出項的值。b.scanf(格式控制,地址列表);。該函數接收計算機鍵盤輸入的數據并賦值給對應的變量。例如:intx=3;chary[3]=“abc”;printf(“x=%d,y=%3s\n”,x,y);scanf(“%d,%c\n”,&x,&y);printf(“x=%d,y=%3s\n”,x,y);其中,格式控制必須包含在一對雙引號內,包括格式說明符(%d)、普通字符(x=,y=)和轉義控制符(\n)三種類型。格式說明符前必須用百分號“%”。常用的格式說明符的含義如表4-1所示。表4-1常用格式字符的含義格式字符說明附加格式字符說明d帶符號的十六進制數m數據長度s字符串n截取字符的個數c一個字符f小數形式的實數nn位小數常用的轉義控制符有兩個:\n:換行。\r:回車。他的前必須用反斜杠“\”。再如,在計算機屏幕上打印99乘法口訣表。參考程序如下所示:/*cfb.c*/#include<reg51.h>//包含51系列單片機頭文件#include<stdio.h>//包含基本輸入、輸出頭文件voidcominit() //設置定時器、串行通信函數{SCON=0x50;//設置串行口控制寄存器

TMOD|=0x20;//設置定時器方式寄存器

TH1=0xf3;//設置定時器1(T1)高8位的初值

TR1=1;//啟動定時器1TI=1;//置位發送標志位}voidmain(void)//主函數{unsignedinti,j;//定義無符號整型變量i與jcominit();//調用設置定時器、串行通信函數for(i=1;i<=9;i++)//外循環{for(j=1;j<=i;j++)//內循環 printf("%dX%d=%d",j,i,i*j);//計算機屏幕上打印一行乘法口訣表 printf("\n");//換行打印}}在keilC51中,為了借助計算機鍵盤與屏幕調試程序,需要模擬單片機串行口與計算機鍵盤與計算機屏幕進行通信。因而需要設置定時器/計數器與串行通信,“voidcominit()”函數就是為此目的而寫的。程序調試運行結果如下所示:1X1=11X2=22X2=41X3=32X3=63X3=91X4=42X4=83X4=124X4=161X5=52X5=103X5=154X5=205X5=251X6=62X6=123X6=184X6=245X6=306X6=361X7=72X7=143X7=214X7=285X7=356X7=427X7=491X8=82X8=163X8=244X8=325X8=406X8=487X8=568X8=641X9=92X9=183X9=274X9=365X9=456X9=547X9=638X9=729X9=81③用戶自定義標題文件。用戶將自己常用的宏定義、條件編譯、圖片代碼、數據表格等組成一個文件,然后在各個源程序中用“#include”命令包含進來,無需重復定義。4.3C51的數據類型、存儲類型及常量與變量

4.3.1C51的數據類型C51的數據類型大體上可以分為基本數據類型、構造數據類型和空類型等三種。其中基本數據類型又可分為位型、無符號字符型、有符號字符型、無符號整型、有符號整型、無符號長整型、有符號長整型、浮點型及雙精度實型等九種類型。它們的符號、長度、值域等如表4-2所示。表4-2C51的數據類型數據類型數據類型名稱長度/bit長度/Byte表示數的范圍bit或sbit位型1—0,1unsignedchar無符號字符型810~255signedchar有符號字符型81-128~+127unsignedint無符號整型1620~65535signedint有符號整型162-32768~+32767unsignedlong無符號長整型3240~4294967295(0~232-1)signedlong有符號長整型324-2147483648~+2147483647(-231~231-1)float單精度實型(浮點型)324±3.4e-38~±3.4e+38(相當于6位有效數字)double雙精度實型648±1.7e-38~±1.7e+38(相當于10位有效數字)4.3.2C51的數據存儲類型(1)數據存儲類型C51允許將變量或常量定義成不同的存儲類型,以使單片機訪問不同的存儲空間。主要包括片內直接尋址型、片內位尋址型、片內間接尋址型、片外分頁尋址型、片外間接尋址型以及代碼型等六種類型,它們和單片機的不同存儲區相對應。如表4-3所示。表4-3C51存儲類型與MCS-51單片機存儲空間的對應關系存儲類型存儲類型名稱長度/bit長度/Byte值域范圍與MCS-51單片機存儲空間的對應關系data片內直接尋址型810~255直接尋址片內低128字節數據存儲器RAMbdata片內位尋址型8132~47按位或字節尋址片內RAM的20H~2FH地址空間idata片內間接尋址型810~255間接尋址片內RAM的00H~FFH地址空間pdata片外分頁尋址型810~255分頁尋址256字節片外RAM,對應MOVX@Rixdata片外間接尋址型1620~65535尋址64K字節片外RAM,對應MOVX@DPTRcode代碼型1620~65535尋址64K字節ROM,對應MOVC@DPTR(2)變量存儲類型定義舉例變量的存儲類型通常與數據類型一起使用。先說明數據類型,再說明存儲類型。現舉例如下:①chardatavar1;//字符型變量var1被定義為data型,被分配在片內RAM中的低128字節中。②bitbdataflags;//位變量flags被定義為bdata型,定位在片內RAM中的位尋址區。③floatidatax,y,z;/*浮點型變量x、y和z被定義為idata存儲類型,定位在片內RAM中,并只能用間接尋址方式進行訪問。*/④unsignedintpdatadimension;/*無符號整型變量dimension被定義為pdata型,定位在片外數據存儲區,相當于用MOVX@Ri訪問。*/⑤unsignedcharxdatavector[10][4][4];/*無符號字符型三維數組變量vector[10][4][4]被定義為xdata存儲類型,定位在片外RAM中,占據10×4×4=160個字節,相當于用MOVX@DPTR訪問。*/(3)存儲模式如果在變量定義時略去存儲類型標志符,則由編譯器(如KeilC51)自動默認存儲類型。默認的存儲類型進一步由SMALL、COMPACT和LARGE存儲模式指令限制。存儲模式的有關說明如表4-4所示。表4-4存儲模式及說明存儲模式模式名稱說

明SMALL小模式參數及局部變量放入可直接尋址的片內存儲器(最大128字節,默認存儲類型是data),因此訪問十分方便。另外所有對象,包括棧,都必須嵌入片內RAM。棧長很關鍵,因為實際棧長依賴于不同函數的嵌套層數。COMPACT一般模式(中模式)參數及局部變量放入分頁片外存儲區(最大256字節,默認存儲類型是pdata),通過寄存器R0和R1間接尋址,棧空間位于內部數據存儲器中。LARGE大模式參數及局部變量直接放入片外數據存儲區(最大64KB字節,默認存儲類型是xdata),使用數據指針DPTR來進行尋址。用此數據指針訪問的效率低,尤其是對二個或多個字節的變量,這種數據類型的訪問機制直接影響代碼的長度,另一個不便之處在于這種數據指針不能對稱操作。4.3.3常量與變量(1)常量在程序運行過程中,其值不能被改變的量稱為常量,如數字、字符等。每種數據類型的數值都有常量。字符型常量用單引號括起來,字符串常量用雙引號括起來,十六進制數常量用“0x+數值”表示。①直接常量(也叫字面常量)。如12、0、0xCE、‘A’、“GUIZHOU”等。②符號常量。符號常量即是用一個標識符來代替一個常量。符號常量通常用前面介紹的宏命令define來定義。如:#definetscr_init0x40#definetmodh_init0#definetmodl_init250也可通過const關鍵字來定義的符號常量。定義形式:數據類型const標識符=數字如:intconstPI=3;區別:用define定義的常量不占任何存儲空間,在編譯時直接用對應的數據代替其常量名稱參與運算。而用const定義的常量則會占去單片機ROM區的內存,占去的空間大小為其定義數據類型所占空間的大小,如上面定義的PI常量占2個字節的空間。(2)變量在程序運行過程中,其值可以被改變的量稱為變量。每個變量都必須有變量名,變量名是標識符,必須滿足用戶標識符的要求。變量必須先定義后使用,定義變量的目的是說明變量的數據類型,以便為變量分配相應的存儲單元。在程序使用變量前最好給變量賦初值,不賦初值的數值型變量其初值為0。變量在定義的同時可以賦初值。如:[static]intx,y=2,j=5;floatsum;以上兩條語句定義了x、y、j三個靜態整型變量和一個浮點型變量sum,并且給變量y賦初值2,j賦初值5,沒有給變量x賦初值,其初值默認為0。其中的存儲類型在需要特別聲明的時候才需要,否則可以省略。同類變量可以共用一個數據類型說明符,各個變量之間用逗號隔開,最后以分號結束。這三個整型變量x、y、j在后面的程序中可以存放整型數據。浮點型變量sum可以存放一個浮點型數據的值。4.4C51對單片機主要資源的定義

4.4.1使用關鍵字定義特殊功能寄存器(SFR)SFR及其可位尋址的位是通過關鍵字sfr和sbit來定義的,這種方法與標準C不兼容,只適用于C51。(1)用sfr定義特殊功能寄存器(SFR)的字節地址①格式:sfr寄存器變量名稱=地址值;②功能:將右邊的地址賦值給左邊的寄存器變量名稱。③舉例:a.sfrPSW=0xD0;//定義程序狀態字寄存器PSW的地址為D0Hb.sfrSCON=0x98;//定義串行口控制寄存器SCON的地址為98Hc.sfrP0=0x80;//定義P0口的地址為80Hd.sfrTMOD=0x89;//定義定時器/計數器方式控制寄存器TMOD的地址為89H(2)用sbit定義特殊功能寄存器(SFR)的位地址①格式:sbit的用法有三種格式,分別介紹如下。a.sbit位變量名稱=位地址值;b.sbit位變量名稱=SFR名稱^變量位地址值;c.sbit位變量名稱=SFR地址值^變量位地址值;②功能:將右邊的位地址賦值給左邊的位變量名稱。③舉例:a.sbitCY=0xD7;//定義進位標志CY的地址為D7Hb.sbitAC=PSW^6;//定義輔助進位標志AC為PSW的第6位,其中PSW必須先用sfr定義好c.sbitRS0=0xD0^3;//定義RS0的地址為D3H(即D0H單元的第3位)注意:用sfr和sbit定義的SFR必須位于函數外,一般放在程序的開頭。

4.4.2通過頭文件訪問特殊功能寄存器(SFR)

頭文件:以“.h”為擴展名的文件。C51編譯器給出的頭文件已經給出了MCS-51單片機中的SFR及其可位尋址位的定義。并且KeilC51編譯器將這些頭文件按單片機的不同生產公司、不同型號分別存放在KeilC51的INC子目錄下,在程序中只需引用這些頭文件即可實現對SFR的訪問和控制。頭文件通常有reg51.h,reg52.h,math.h,ctype.h,stdio.h,stdlib.h,absacc.h,intrins.h等八個。但常用的卻只有reg51.h或reg52.h,math.h等二個。reg51.h或reg52.h是定義51單片機或52單片機特殊功能寄存器和位寄存器的,這兩個頭文件中大部分內容是一樣的,52單片機比51單片機多一個定時器T2,因此,reg52.h中也就比reg51.h多幾行定義T2的內容。math.h是定義常用數學運算的,比如求絕對值、求方根、求正弦或余弦等,該頭文件中包含有各種數學運算函數,當我們需要使用時可以直接調用它的內部函數。在代碼中引用頭文件,其實際意義就是將這個頭文件中的全部內容放到引用頭文件的位置,從而免去我們每次編寫同類程序時都要將頭文件中的語句重復編寫。打開reg51.h,其全部內容見教材所示。舉例如下:#include<reg51.h>//使用的單片機為AT89C51main(){TL0=0xb0;//訪問定時器0,設置時間常數TH0=0x3c;TR0=1;//啟動定時器0┅}4.4.3擴展I/O端口或片外RAM的直接訪問

擴展的片外RAM或I/O端口需要用戶自己先定義后才能在語句或函數中使用。現舉例如下:#include<absacc.h>/*包含頭文件absacc.h,其內部將XBYTE定義為一個指針,指向外部數據存儲器RAM的零地址單元*/#definePAXBYTE[0xffec]//將PA定義為外部I/O口,地址為0xffecmain(){PA=0x3a;//將數據3AH寫入地址為0xffec的存儲單元或I/O端口}4.4.4定義和使用位變量

C51使用關鍵字“bit”來定義位變量。格式:bit變量名稱;功能:將變量名稱定義為位型變量。例:bitlock;//將lock定義為位變量bitdirention;//將dirention定義為位變量函數既可以有bit類型的參數,也可以有bit類型的返回值。例如:bitfunc(bitb0,bitb1){bita;┅return(a);}4.5C51的基本運算

4.5.1C51的算術運算(1)基本的算術運算符①+:加法運算符。②-:減法運算符。③*:乘法運算符。④/:除法或求模運算符。⑤%:取余運算符。(2)自增、自減運算符①++:自增運算符。②--:自減運算符。例如:++j、j++、--j、j--注意:++和--運算符只能用于變量,不能用于常量和表達式。++j表示先加1,再取值;而j++表示先取值,再加1。自減運算也是如此。(3)算術表達式和運算符的優先級與結合性①算術表達式就是用算術運算符和括號將運算對象連接起來的式子。例如:(2a+3b)*c/d。②C51規定了算術運算符的優先級為先乘除和取模,后加減,括號最優先。③C語言中各運算符的結合性分為兩種,即左結合性(自左至右)和右結合性(自右至左)。算術運算符均為左結合性,即先左后右。例如表達式x-y+z,則y應先與“-”號結合,執行x-y運算,然后再執行+z的運算。這種自左至右的結合方向就稱為“左結合性”。而自右至左的結合方向稱為“右結合性”。最典型的右結合性運算符是賦值運算符。如x=y=z,由于“=”的右結合性,應先執行y=z,再執行x=(y=z)運算。④不同數據類型間的轉換。其一是自動類型轉換,即在程序編譯時,由C編譯器自動進行數據類型轉換。其二是使用強制類型轉換運算符。語句形式為:(類型說明符)(表達式)。功能:把表達式的運算結果強制轉換成類型說明符所表示的類型。例如:inta,b;//a、b為整數(double)(a+b);//將a+b強制轉換成double數據類型4.5.2C51的關系運算(1)關系運算符及其優先級關系運算符也叫比較運算符,C51提供了以下6種關系運算符。①<:小于運算符。④>=:大于等于運算符。②<=:小于等于運算符。⑤==:等于運算符。③>:大于運算符。⑥!=:不等于運算符。在以上運算符中,<、<=、>、>=這四個運算符的優先級相同,處于高優先級;==和!=這兩個運算符的優先級也相同,處于低優先級。此外,關系運算符的優先級低于算術運算符的優先級,而高于賦值運算符的優先級。(2)關系表達式關系表達式:用關系運算符將運算對象連接起來的式子。如:a>b、(a=4)<(b=3)等。關系表達式的值為邏輯值,其結果只能是真和假兩種值之一。C51中用1表示真,用0表示假。4.5.3C51的邏輯運算(1)邏輯運算符及其優先級邏輯運算是對變量進行邏輯與運算、或運算及非運算。①&&:邏輯與運算符。②||:邏輯或運算符。③!:邏輯非運算符。其中非運算的優先級最高,而且高于算術運算符;或運算的優先級最低,低于關系運算符,但高于賦值運算符。(2)邏輯運算表達式邏輯運算表達式:用邏輯運算符將運算對象連接起來的式子。例如:(a>b)||c&&!d,表示a大于b的值跟c與d非的值相或。邏輯表達式的值與關系表達式的值一樣,也是邏輯量,即真或假。4.5.4C51的位運算位運算的操作對象只能是整形和字符型數據,而不能是實型數據。①&:按位與運算符,兩個字符或整數按位進行邏輯與運算。例如:var3=var1&var2。②|:按位或運算符,兩個字符或整數按位進行邏輯或運算。例如:var3=var1|var2。③^:按位異或運算符,兩個字符或整數按位進行邏輯異或運算。例如:var3=var1^var2。④~:按位取反運算符,兩個字符或整數按位進行邏輯非運算。例如:var1=~var2。⑤<<:左移運算符,字符或整數按位進行邏輯左移運算。例如:var1=var2<<4。⑥>>:右移運算符,字符或整數按位進行邏輯右移運算。例如:var1=var2>>6。4.5.5C51的賦值運算(1)賦值運算符賦值符號“=”完成的操作即為賦值運算,它是右結合性,且優先級最低。(2)賦值表達式將一個變量與表達式用賦值號連接起來就構成賦值表達式。形式如下:變量名=表達式功能:將“=”右邊表達式的值賦給“=”左邊的一個變量。例如:a=(b=4)+(c=6),該表達式的值為10,變量a的值也為10。(3)賦值的類型轉換規則在賦值運算中,當賦值運算符“=”兩側的類型不一致時,系統自動將右邊表達式的值轉換成左側變量的類型,再賦給該變量。轉換規則如下。①實型數據賦給整型變量時,舍棄小數部分。②整型數據賦給實型變量時,數值不變,但以IEEE浮點數形式存儲在變量中。③長字節整型數據賦給短字節整形變量時,實行截斷處理。如將long型數據賦給int型變量時,將long型數據的低兩字節數據賦給int型變量,而將long型數據的高兩字節的數據丟棄。④短字節整型數據賦給長字節整型變量時,進行符號擴展。如將int型數據賦給long型變量時,將int型數據賦給long型變量的低兩字節,而將long型變量的高兩字節的每一位都設為int型數據的符號值。(4)復合賦值運算符賦值符號前加上其它運算符即構成復合運算符。+=,-=,*=,/=,%=,&=,|=,^=,<<=,>>=。其功能是先進行加、減、乘、除、取余、與、或、異或、左移以及右移運算后再進行賦值操作。例如:a+=b;//等價于a=(a+b),賦值表達式加上分號即“a+=b;”也叫賦值語句x*=a+b;//等價于x=x*(a+b)a&=b;//等價于a=(a&b)a<<=4;//等價于a=(a<<4)4.6C51的構造數據類型

4.6.1數組

數組是同類型數據的一個有序集合。它必須由具有相同數據類型的元素構成,這些數據的類型就是數組的基本類型。例如,若數組中的所有元素都是整型,則該數組稱為整型數組,若所有元素都是字符型,則該數組稱為字符型數組。數組用一個名字來標識,稱為數組名。數組中各元素的順序用下標來標識,下標為n的元素可以表示為:數組名[n]。改變[]中的下標就可以訪問數組中所有的元素。但應注意,數組必須先定義,后使用。根據下標的多少,可將數組分為一維數組、二維數組和多維數組,它們的定義形式不同。(1)一維數組一維數組是指由只具有一個下標的數組元素組成的數組。定義形式如下:類型說明符數組名[元素個數];例如:intdemol[10];//定義一個名為demol的整型數組,數組包含10個元素在定義時賦初值的方法:①在定義數組時對數組的全部元素賦予初值。例如:inta[5]={1,2,3,4,5};//給全部元素賦值,a[0]=1,a[1]=2,a[2]=3,a[3]=4,a[4]=5。②只對數組的部分元素初始化。例如:intb[6]={1,2};//給部分元素賦值,b[0]=1,b[1]=2,b[2]=b[3]=b[4]=b[5]=0。③在定義數組時對數組的全部元素不賦初值,則數組元素值均被初始化為0。④可以在定義時不指明數組元素的個數,而根據賦值部分由編譯器自動確定。例如:ucharBitTab[]={0x7F,0xBF,0xDF,0xEF,0xF7,0xFB};這相當于定義了一個BitTab[6]這樣一個數組。⑤可以為數組指定存儲空間。若未指定空間時,則將數組定義在內部RAM中,而當用關鍵字code定義時,將數組元素定義在ROM空間中。例如:ucharcodeBitTab[]={0x7F,0xBF,0xDF,0xEF,0xF7,0xFB};這種方式適用于編程中不需要改變內容的場合,如顯示用LED數碼管的字形碼等是很合適的。⑥C語言并不對越界使用數組進行檢測。例如上例中數組的長度是6,其元素應該是從BitTab[0]到BitTab[5],但是如果你在程序中寫上BitTab[6],編譯器并不會認為這有語法錯誤,也不會給出警告(其他語言如BASCI等則有嚴格的規定,這種情況將視為語法錯誤),因此,編程者必須自己小心確認這是否是你需要的結果。(2)二維數組或多維數組數組的下標具有兩個或兩個以上,則稱為二維數組或多維數組。定義二維數組的一般形式:類型說明符數組名[行數][列數];例如:floatdemo2[3][4];//demo2數組有3行4列共12個實型元素。二維數組既可以在定義時進行整體初始化,也可在定義后單個地進行賦值。例如:inta[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};//全部初始化結果為a[0][0]=1,a[0][1]=2,a[0][2]=3,a[0][3]=4,a[1][0]=5,a[1][1]=6,a[1][2]=7,a[1][3]=8,a[2][0]=9,a[2][1]=10,a[2][2]=11,a[2][3]=12。intb[3][4]={{1,2,3,4},{5,6,7,8},{}};//部分初始化(3)字符數組若一個數組的元素是字符型的,則該數組就是一個字符數組。例如:chara[8]={“JiXie”};//字符數組charadd[3][6]={“weight”,“height”,“width”};//字符串數組4.6.2結構(1)結構類型的定義(有三種方法)①先定義結構類型,再定義結構變量名定義結構類型的一般格式為:struct結構類型名{結構元素表;//與定義基本數據類型相似};例如:structdate{intyear;charmonth;charday;};定義好一個結構類型之后,就可以用它來定義結構變量。一般格式為:struct結構名結構變量名1,結構變量名2,…,結構變量名n;例如,可以用結構date來定義兩個結構變量d1和d2。其格式為:structdated1,d2;//結構變量d1和d2都具有structdate的結構。②在定義結構類型的同時定義結構變量名這種方法是將方法1的兩個步驟合在一起,一般格式為:struct結構類型名{結構元素表;//與定義基本數據類型相似}結構變量名1,結構變量名2,…,結構變量名n;例如,對于上述日期結構變量也可按以下格式定義:structdate{intyear;charmonth;charday;}d1,d2;③直接定義結構變量這種方法可以省掉結構名,又稱為無名結構,一般格式為:struct{結構元素表}結構變量名1,結構變量名2,…,結構變量名n;例如,上述日期結構變量可以按以下格式定義:struct{intyear;charmonth;charday;}d1,d2;

第③種方法與第②種方法十分相似,所不同的只是第③種方法中省略了結構名“date”。這種方法一般只用于定義幾個確定的結構變量的場合。(2)結構類型變量的引用使用成員運算符“.”實現對結構成員的引用。引用格式:結構變量名.結構元素例如,d1.year表示結構變量d1中的元素year,d2.day表示結構變量d2中的元素day等。如果一個結構變量中的結構元素又是另外一個結構變量,即出現結構的嵌套時,則需要采用若干個成員運算符,一級一級地找到最低一級的結構元素,而且只能對這個最低級的結構元素進行訪問。對結構變量中的各個元素可以像普通變量一樣進行賦值、存取和運算。例如:d1.year=2009;sum=d1.day+d2.day;d1.month++;m1.time.hour=0x22;其中成員運算符“.”的優先級別最高,因此d1.month++是對d1.month進行自加運算,而不是先對month進行自加運算。m1.time.hour=0x22是對嵌套結構類型中最低一層的結構元素進行訪問。4.6.3聯合(1)聯合與結構的比較與結構相似,在一個聯合中也可以包含多個不同類型的數據元素。但在內存的分配上,聯合與結構有著本質的區別。結構變量所占用的內存長度是其中各個元素所占內存長度的總和,而聯合變量所占用的內存長度是其中最長元素的長度。因為聯合變量是采用所謂的“覆蓋技術”對內存進行分配的。這種技術可使不同的變量分時使用同一個內存空間,從而提高內存的利用效率。即聯合為程序提供了一個不關心機器結構而又能在同一存儲區處理不同數據類型的方法。例如,可將一個float型變量、一個int型變量、一個char型變量放在同一個地址開始的內存單元中,如圖4-3所示。以上三個變量在內存中的字節數不同,但卻都從同一地址開始存放,這就是所謂的“覆蓋技術”。floatiintjchark起始地址圖4-3聯合中變量的存儲方法(2)聯合類型的定義(與結構相似,聯合也有三種定義方法)。①先定義聯合類型,再定義聯合變量名定義聯合類型的一般格式為:union聯合類型名{聯合成員說明;//與定義基本數據類型相似};其中“聯合成員說明”為該聯合中的各個成員(又稱為聯合的域),由于聯合可以由不同類型的數據組成,因此對聯合中的各個成員都要進行類型說明。例如,一個名為date的聯合類型可以定義如下:uniondate{intival;floatfval;

charsval;

};定義好一個聯合類型之后,就可以用它來定義聯合變量了。其定義格式為:union聯合類型名聯合變量名1,聯合變量名2,…,聯合變量名n例如,可以用聯合date來定義三個結構變量a、b、c。其格式為:uniondatea,b,c;聯合變量a、b、c都具有uniondate類型的結構,即它們都是由一個整型數據、一個浮點型數據和一個字符型數據所組成的。并且,變量a,b,c將足夠大,使其能夠容納這三種類型中的最大者,具體的長度與操作無關。②在定義聯合類型的同時定義聯合變量名這種方法是將方法①的兩個步驟合在一起,一般格式為:union聯合類型名{聯合成員說明;//與定義基本數據類型相似}變量列表;例如,對于上述date聯合變量也可按以下格式定義:uniondate{intival;floatfval;charsval;}a,b,c;③直接定義聯合變量這種方法可以省掉聯合名,又稱為無名聯合,一般格式為:union{聯合成員說明}結構變量名1,結構變量名2,…,結構變量名n;例如,上述a、b、c聯合變量也可以按以下格式定義:union{intival;floatfval;

charsval;

}a,b,c;第③種方法與第②種方法十分相似,所不同的只是第③種方法中省略了聯合名“date”。這種方法一般只用于定義幾個確定的聯合變量的場合。在上例中,如果只需要定義a、b和c而不打算再定義任何別的聯合變量,則可省掉聯合名“date”。不過為了便于記憶和以備將來進一步定義其他聯合變量的需要,一般還是不要省掉聯合名為好。(2)聯合類型變量的引用與結構變量類似,對聯合變量的引用也是通過對其聯合元素的引用來實現的。格式:聯合變量名.聯合元素或聯合變量名->聯合元素。例如:對于前面定義的聯合變量a、b、c,下面的引用方法都是正確的:a.fval/*引用聯合變量a中float型元素fval*/b.ival/*引用聯合變量b中int型元素ival*/c->sval/*引用聯合變量c中char型元素sval*/注意:①在引用聯合元素時,要注意聯合變量用法的一致性。因為聯合類型中定義的各個不同類型的元素都可以分時地賦給變量,而所讀取變量的值是最近放入的某一元素的值,因此在表達式中對它進行處理時,必須注意其類型與表達式所要求的類型保持一致,否則將導致程序運行出錯。不能只引用聯合變量。例如,下面的寫法就是錯誤的:printf(“%f”,a);因為變量a可能是float、int和char三種類型,分別占用不同長度的內存區域,若在引用時僅寫聯合變量名a,系統將難以確定究竟應該輸出哪一個聯合元素的值。正確的寫法應為:printf(“%f”,a.ival);②聯合類型的數據可以采用同一個內存段來存放幾種不同類型元素的值,但是在每一瞬時只能存放其中一種類型的元素,而不能同時存放幾種。換句話說,每一瞬時只有一個元素在起作用。起作用的是聯合中最后一次存放的元素,如果存入了一個新的元素,則上次存入的元素就自動失去作用。例如,對于下列語句:a.fval=100.25;a.ival=200;a.sval=10;在執行以上三條賦值語句之后,只有a.sval是有效的,而a.ival和a.fval都已失去作用。因此在引用聯合變量時一定要十分注意當前在聯合變量中存放的究竟是哪一個元素。不能直接對聯合變量進行賦值,也不能在定義聯合變量時對它進行初始化。4.7C51的流程控制語句

4.7.1選擇控制語句(有if語句和switch/case語句,用于設計分支結構程序)(1)if語句if語句是用來判定所給定的條件是否滿足,再根據判定的結果(真或假)來決定執行給出的兩種操作之一。C51提供了三種形式的if語句。①形式1。格式:if(表達式){語句;}功能:如果表達式的結果為真,則執行語句,否則不執行。②形式2。格式:if(表達式){語句1;}else{語句2;}功能:如果表達式的結果為真,則執行語句1,否則執行語句2。③形式3。格式:if(表達式1){語句1;}elseif(表達式2){語句2;}elseif(表達式3){語句3;}…elseif(表達式m){語句m;}else{語句n;}功能:這是if語句的嵌套,即一個if語句中又包含有一個或多個if語句。主要用于多分支選擇程序。在if語句的嵌套中應注意if與else的對應關系,else總是與它前面最近的一個if語句相對應。【例4.1】

某浮點數的范圍在0.000~9999之間,試編寫一個函數返回浮點數的小數點位置。解:此題的基本思路是根據浮點數的4種不同取值范圍給出4種不同的返回值。可以約定浮點數的大小在0.000~9.999、10.00~99.99、100.0~999.9、1000~9999之間時,分別返回0、1、2和3。參考程序如下:intftochar(floatvalp){intdotno=0;if(valp<10.00)dotno=0;elseif((valp>=10.0)&&(valp<100.0)dotno=1;elseif((valp>=100.0)&&(valp<1000.0)dotno=2;elseif(valp>=1000.0)dotno=3;returndotno;}根據小數點的位置,即可在實際的單片機系統中顯示出浮點數或小數。(2)switch/case語句(用于直接處理多分支選擇)switch/case語句的一般形式如下:switch(表達式){case常量表達式1:語句1;break;case常量表達式2:語句2;break;……case常量表達式n:語句n;break;default:語句n+1;}說明:當switch后面括號內的“表達式”的值與某一個case后面的常量表達式的值相等時,就執行此case后面的語句(可以是復合語句),遇到break語句就退出switch語句。若所有的case中的常量表達式的值都沒有與表達式的值匹配時,就執行default后面的語句。【例4.2】

AT89C51單片機的P1.1和P1.0引腳接有兩只按鍵,其4種邏輯組合分別點亮由P2.0~P2.3控制的4只LED(高電平點亮),試編程實現此功能。解:參考程序如下:#include<at89x51.h>//包含AT89x51系列單片機的頭文件voidmain(){chara;do

{a=P1;

a=a&0x03;//屏蔽掉P1口的高6位

P2=P2&0xf0;//開始4只LED全熄

switch(a){case0:P2=P2|0x01;break;case1:P2=P2|0x02;break;case2:P2=P2|0x04;break;case3:P2=P2|0x08;}}while(1);//循環繼續讀取按鍵}4.7.2循環控制語句循環程序可分為“當型”循環程序和“直到型”循環程序兩種類型,這與其它語言的循環程序一樣。在C51語言中,用來構成循環控制的語句有:while語句、do-while語句、for語句以及if和goto語句等。(1)基于while語句構成的循環采用while語句構成循環結構的一般格式如下:while(條件表達式){內部語句;//內部語句可以是復合語句,也可以為空}意義:當條件表達式的結果為真(非0值)時,程序就重復執行后面的內部語句,一直執行到條件表達式的結果變為假(0值)時為止。也就是說,這種循環結構是先檢查條件表達式所給出的條件,再根據檢查的結果決定是否執行后面的內部語句。如果條件表達式的結果一開始就為假,則后面的內部語句一次也不會執行。因此屬于“當型”循環。圖4-4為while語句的執行過程。

假條件表達式內部語句真圖4-4while語句的執行過程【例4.3】

使用while語句計算自然數1~100的累加和,并用printf()函數通過單片機的串口顯示在終端上。解:參考程序如下:#include<stdio.h>/*包含基本輸入輸出頭文件stdio.h*/真內部語句條件表達式假圖4-5do-while語句循環結構的流程圖voidmain(){inti,sum=0;i=1;while(i<=100){/*復合語句循環體開始*/sum=sum+i;i++;}/*復合語句循環體結束*/printf(“1+2+…+100=%d\n”,sum);while(1);}(2)基于do-while語句構成的循環do-while語句只能用來實現“直到型”循環,其一般格式如下:do{內部語句;//可以是復合語句}while(條件表達式);意義:先執行給定的循環體語句,然后再檢查條件表達式的結果。當條件表達式的值為真(非0值)時,則重復執行循環體語句,直到條件表達式的值變為假(0值)時為止。因此,用do-while語句構成的循環結構在任何條件下,循環體語句至少會被執行一次,這就是“直到型”循環。圖4-5給出了這種循環結構的流程圖。真內部語句條件表達式假圖4-5do-while語句循環結構的流程圖【例4.4】實型數組sample存有10個采樣值,編寫一個函數返回其平均值(即平均值濾波程序)。解:參考程序如下:floatavg(float*sample){floatsum=0;charno=0;do{sum+=sample[no];no++;}while(no<10);return(sum/10);}假初值設定表達式內部語句更新表達式循環條件表達式真圖4-6for語句的執行過程示意圖(3)基于for語句構成的循環采用for語句構成循環結構的一般格式如下:for([初值設定表達式];[循環條件表達式];[更新表達式]){內部語句;//可以是復合語句}意義:先計算出初值設定表達式的值作為循環控制變量的初值,再檢查循環條件表達式的結果,當滿足條件時就執行循環體語句并計算更新表達式,然后再根據更新表達式的計算結果來判斷循環條件是否滿足,只有一直進行到循環條件表達式的結果為假(0值)時才退出循環體。各表達式之間必須用分號“;”進行分隔。for語句的執行過程如圖4-6所示。【例4.5】

使用for語句計算自然數1~100的累加和,并用printf()函數通過單片機的串口顯示在終端上。解:參考程序如下:#include<aduc812.h>#include<stdio.h>intgetsum(void);voidmain(){SCON=0x50;//如果用KeilC進行模擬調用或使用printf(),必須初始化SCONTMOD=TMOD|0x20;//定時器T1工作方式2,用做波特率控制TH1=0xfd;//9600bps對應T1的時間常數為0xfdTL1=0xfd;TR1=1;//啟動T1TI=1;//啟動發送,以發送第一個字符printf(“%d\n”,getsum());do{}while(1);}intgetsum(void){intsum=0;intn;for(n=1;n<=100;n++){sum=sum+n;}return(sum);}(4)基于if和goto構成的循環①“當型”循環。采用if和goto可以構成“當型”循環程序,其格式如下:loop:if(條件表達式){內部語句;//可以是復合語句gotoloop;}說明:loop是語句標號,實質是帶冒號“:”的標識符,原則上任何一條語句都可以有標號,標號和語句之間用冒號“:”分隔。其執行過程是首先判斷條件表達式的值,當條件表達式的值為真(非0值)時,則執行內部語句,遇到gotoloop語句時則無條件返回loop處繼續判斷條件表達式的值。直到條件表達式的值為假(0值)時才退出循環。需注意的是,條件表達式中條件變量的值必須在內部語句中進行改變,否則就成為死循環程序。②“直到型”循環。采用if和goto也可以構成“直到型”循環程序,其格式如下:loop:{內部語句;//可以是復合語句if(條件表達式)gotoloop;}說明:首先執行內部語句(即循環體),再判斷條件表達式的值。若條件表達式的值為真(非0值)時,則執行gotoloop語句,無條件返回loop處繼續執行內部語句(即循環體)。當條件表達式的值為假(0值)時就退出循環。顯然,條件表達式的值不能一直為真(非0值),否則就成為死循環程序。③goto語句。goto語句是一個無條件轉向語句,它的一般形式為:goto語句標號;前已述及,語句標號是一個帶冒號“:”的標識符,將goto語句和if語句相結合使用,就可以構成“當型”循環或“直到型”循環結構。【例4.6】

使用goto語句跳出循環結構。本程序采用循環結構來求一個整數的等差數列,該數列滿足條件:頭四個數的和值為26,積值為880。該數列的公差應為正整數,否則將產生負的項,此外該數列的首項數必須小于5,且其公差也應小于5,否則頭四項的和值將大于26。解:參考程序如下:#include<stdio.h>voidmain(){inta,b,c,d,i;for(a=1;a<5;++a){for(d=1;d<5;++d){

b=a+(a+d)+(a+2*d)+(a+3*d);

c=a*(a+d)*(a+2*d)*(a+3*d);if(b==26&&c==880)gotopt;}}pt:for(i=0;i<=10;++i)printf(“%d,”,a+i*d);

printf(“…\n”);while(1);}④continue語句。

在循環結構中還可以使用一種中斷語句continue,它的功能是結束本次循環,即跳過循環體中下面尚未執行的語句,把程序流程轉移到當前循環語句的下一個循環周期,并根據循環控制條件決定是否重復執行該循環體。continue語句的一般格式為:continue;

continue語句通常和條件語句一起用在由while、do-while和for語句構成的循環結構中,它也是一種具有特殊功能的無條件轉移語句,但與goto、break語句不同,continue語句并不跳出循環體,而只是根據循環控制條件確定是否繼續執行循環語句。【例4.7】

利用continue語句把10~20之間不能被3整除的數輸出。解:參考程序如下:#include<stdio.h>voidmain(){intn;for(n=10;a<=20;n++){if(n%3==0)continue;printf(“%d”,n);}while(1);}4.8C51的函數

4.8.1函數的分類與定義(1)函數的分類①主函數main()。關于主函數main(),我們應該很熟悉了。下面再簡要介紹其格式和特點。格式:voidmain()/*注意:后面沒有分號*/{總程序從這里開始執行;其他語句;……}特點:無返回值,無參數。

無返回值表示該函數執行完后不返回任何值,上面main前面的void表示“空”,即不返回值的意思。無參數表示該函數不帶任何參數,即main后面的括號中沒有任何參數,只寫“()”就可以了,也可以在括號里寫上void,表示空的意思,如voidmain(void)。②普通函數。a.標準庫函數。b.用戶自定義函數。(2)函數的定義函數定義的一般形式為:函數類型函數名(形式參數列表)形式參數說明{局部變量定義;函數體語句;}其中,“函數類型”說明了自定義函數返回值的類型。返回值的類型可以是基本數據類型(如int、char、float、double等),也可以是指針類型。當函數沒有返回值時,則使用標識符void進行說明。若沒有指定函數的返回值類型,則默認返回值為整型類型。一個函數只能有一個返回值,該返回值是通過函數中的return語句獲得的。“函數名”是用標識符表示的自定義函數的名字,它必須是一個合法的標識符。“形式參數列表”中列出的是在主調用函數與被調用函數之間傳遞數據的形式參數,形式參數的類型必須加以說明。形式參數可以是基本數據類型的數據、指針類型數據、數組等。在沒有調用函數時,函數的形式參數和函數內部的變量未被分配內存單元,即它們是不存在的。如果定義的是無參數函數,可以沒有形式參數,但圓括號不能省略。“局部變量定義”是對在函數內部使用的局部變量進行定義。局部變量是定義在函數內部的變量,編譯器只在定義該變量的函數范圍內給其分配存儲空間。一旦調用結束,即刻釋放所分配的內存單元。不同函數中的局部變量可以同名,但編譯器會給它們分配不同的存儲空間。形式參數也是一種局部變量。如果將變量定義在主函數之前,則成為全局變量。在其他函數中不加定義即可使用全局變量,各個函數對全局變量的賦值都會引起全局變量內容的變化,因為各個函數修改的是同一個存儲單元的內容。對同一名稱變量,如果在某一函數中有對該變量的定義(靜態變量除外),則該變量在這個函數中成為局部變量,而在該函數之外是全局變量。“函數體語句”是為完成該函數的特定功能而設置的各種語句。在函數體中可以根據用戶自己的需要,設置各種不同的語句。這些語句應能完成所需要的功能。【例4.8】

定義一個計算整數的正整數次冪的函數。解:參考程序如下:intpower(x,n)intx,n;{inti,p;p=1;for(i=1;i<=n;++i)p=p*x;return(p);}這里定義了一個返回值為整型的函數power(),它有兩個形式參數:x,n。形式參數的作用是接受從主調用函數傳遞過來的實際參數的值。上例中形式參數x和n被說明為int類型。大括號以內的部分是自定義函數的函數體。上例中在函數體內定義了兩個局部變量i和p,它們均為整型數據。需要注意的是,形式參數的說明與函數體內局部變量的定義是完全不同的兩個部分,前者應寫在大括號的外面,而后者是函數體的一個組成部分,必須寫在大括號里面。(3)返回語句return返回語句用于終止函數的執行,并控制程序返回到調用該函數時所處的位置。返回語句有兩種格式:return(變量或表達式);或者return;

①如果return語句后邊帶有變量或表達式,則要計算該變量或表達式的值,并將該變量或表達式的值作為該函數的返回值返回到主調用函數中去。函數返回值的類型就是該函數的類型,因此在定義一個函數時,函數本身的類型應與return語句中變量或表達式的值的類型一致。如果函數的類型與return語句中變量或表達式的值的類型不一致,則以函數的類型為準。對于數值數據可以自動進行轉換,即函數的類型決定返回值的類型。

②若使用不帶表達式的第2種形式,則被調用函數返回主調用函數時,函數值不確定。一個函數的內部可以含有多個return語句,但程序僅執行其中的一個return語句而返回主調用函數。

③如果不需要被調用函數返回一個確定的值,則可以不要return語句。在這種情況下,當程序執行到最后一個界限符“}”處時,就自動返回主調用函數。對于不需要有返回值的函數,可以將該函數定義為void類型(空類型)。4.8.2函數的調用(1)函數的調用形式C語言程序中函數是可以互相調用的。所謂函數調用就是在一個函數體中引用另外一個已經定義了的函數,前者稱為主調用函數,后者稱為被調用函數。函數調用的一般形式如下:函數名(實際參數列表);

“函數名”指出被調用的函數。“實際參數列表”中可以包含多個實際參數,各個參數之間必須用逗號隔開。實際參數的作用是將它的值傳遞給被調用函數中的形式參數。因此,函數調用中的實際參數與函數定義中的形式參數必須在數量、類型以及順序上嚴格保持一致,以便將實際參數的值正確地傳遞給形式參數。否則在函數調用中會產生意想不到的結果。實際參數可以是常數,也可以是變量或表達式,但要求它們具有確定的值。如果調用的是無參函數,則可以沒有實際參數列表,但圓括號不能省略。在C語言中可以采用三種方式完成函數的調用:①函數語句:指在主調函數中將函數調用作為一條語句使用。例如:fun1();這是無參函數,它不要求被調用函數返回一個確定的值,只要求它完成一定的操作。②函數表達式:指在主調用函數中將函數調用作為一個運算對象直接出現在表達式中,這種表達式就稱為函數表達式。例如:c=power(x,n)+power(y,m);實際上,這是一個賦值語句,它包含兩個函數調用,每個函數調用都有一個返回值,將兩個返回值相加的結果賦值給變量c。因此這種函數調用方式要求被調用函數返回一個確定的值。③函數參數:指在主調用函數中將函數調用作為另一個函數調用的實際參數。例如:y=power(power(i,j),k);其中,函數調用power(i,j)放在另一個函數調用power(power(i,j),k)的實際參數列表中,以其返回值作為另一個函數調用的實際參數。這種在調用一個函數的過程中又調用了另外一個函數的方式,稱為嵌套函數調用。(2)在主調用函數中對被調用函數的說明與使用變量一樣,在調用一個函數之前(包括標準庫函數),必須對該函數的類型進行說明,即“先說明,后調用”。函數說明的一般形式:類型標識符被調用的函數名(形式參數列表);其中,“類型標識符”說明了函數返回值的類型。“形式參數列表”中說明各個形式參數的類型。

注意:

①函數的說明與函數的定義是完全不同的。

②如果被調用函數是在主調用函數的前面定義的,或者已經在程序文件的開始處說明了所有被調用函數的類型,在這兩種情況下不必再對被用函數進行說明。

③可以將所有用戶自定義函數的說明另存為一個專門的頭文件,需要時用#i

溫馨提示

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

評論

0/150

提交評論