《程序設(shè)計與C語言》課件第3章_第1頁
《程序設(shè)計與C語言》課件第3章_第2頁
《程序設(shè)計與C語言》課件第3章_第3頁
《程序設(shè)計與C語言》課件第3章_第4頁
《程序設(shè)計與C語言》課件第3章_第5頁
已閱讀5頁,還剩138頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

第3章C語言基本知識3.1C語言基本元素3.2C的基本數(shù)據(jù)類型

3.3C的運算符及表達式

習題3

3.1C語言基本元素3.1.1C的字符集

C語言中可用的字符有以下幾類:

(1)大小寫的英文字母:A,B,…,Z,a,b,…,z。

(2)阿拉伯數(shù)字:0,1,2,3,4,5,6,7,8,9。

(3)特殊字符:+,-,*,/,%,=,-,(,),&,#,!,|,<,>,·,,,;,:,″,′,?,{,},~,\,[,],^,共29個。

(4)不可打印的字符:空格,換行符,制表符。3.1.2標識符標識符是某種對象的名字或標記,這些對象可以是變量名、函數(shù)名、標號等。標識符的構(gòu)成成分是:字母、數(shù)字和下劃線;構(gòu)成規(guī)則是:以字母或下劃線開頭的字符序列。對象的取名最好能直觀表達該對象的意義,這樣能很自然地引起聯(lián)想,便于閱讀和理解。比如表示圓周率可取名pi,表示求和可取名sum等。在C語言中,大寫、小寫字母表示不同的意義,這樣sum和SUM就是兩個不同的名字,甚至sum和sUm也不相同。正確的標識符:abc,_ab2,_123,total等。不正確的標識符:123,abc,ab*c等。3.1.3關(guān)鍵字

C語言中有一種特殊的標識符,它們在程序中有特定的含義,用在特定的地方,不能隨便移作它用。這些標識符是C語言本身帶來的,用戶在定義對象名時不能使用它們。這樣的標識符稱為關(guān)鍵字或保留字,它們都是一些英文單詞或縮寫。C語言的關(guān)鍵字如下:autobreakcasecharconstcontinuedefaultdodoubleelseenumexternfloatforgotoifintlongregisterreturnshortsignedsizeofstaticstructswitchtypedefunionunsignedvoidvolatilewhile共有32個,不需要死記,當學習過它們?nèi)绾问褂煤?,自然就會熟悉起來。而在以后的學習中,就要注意它們都用在什么地方,起什么作用,如何使用它們來構(gòu)成程序。3.1.4變量和常量

1.常量常量是其值在程序執(zhí)行過程中不變的量,如123,45.2,′a′,″abc″等,這樣的常量也稱為常量直接量,因為其含義是由其字面意義直接表達的。還有一種常量稱為符號常量,是用一個名字來代表常量。定義符號常量的方法是用define命令把一個常量名和常量聯(lián)系起來。如 #defineNULL0就定義了一個常量名NULL,它代表0,以后在程序中遇到NULL,就用0來代替。符號常量一般用大寫字母表示,以區(qū)別于變量。當然也不一定非要大寫,也可以用小寫字母表示。

2.變量變量是其值在程序執(zhí)行過程中可以改變的量。如定義sum是個變量,則執(zhí)行語句

sum=0;后,它的值為0,再執(zhí)行語句

sum=1;之后,它的值就變?yōu)?。之所以會有這些變化,是因為變量實際上是內(nèi)存中的一段存儲單元,里面可以存放變化的數(shù)據(jù)。要想把內(nèi)存中的某段存儲單元和一個變量名聯(lián)系起來,必須首先對變量進行定義或聲明。變量聲明的一般形式是:

〈變量類型〉〈變量列表〉;其中,〈變量類型〉是C語言中可以使用的數(shù)據(jù)類型;〈變量列表〉則由一個或多個用逗號分開的標識符(即變量名)組成,最后以分號結(jié)束。如語句

intsum,i;就定義了兩個變量sum和i,它們的類型是整型。這樣就在內(nèi)存中開辟出了兩個能存放整數(shù)的存儲單元。當執(zhí)行語句

sum=0;i=1;之后,變量sum和i的存儲單元為:0sum1i如果再執(zhí)行語句

sum=i+2;則存儲單元變?yōu)椋簩來說,是取出它的值1去和2相加,其存儲單元并未加以改變,這稱為“非破壞性讀出”;而變量sum的存儲單元卻發(fā)生了改變,這稱為“破壞性讀入”。當把一個值放入一個存儲單元時,都會覆蓋掉該單元中原有的內(nèi)容。3sum1i對變量必須先聲明后使用的原因在于:

(1)不同類型的數(shù)據(jù)在編譯時分配的內(nèi)存空間大小不同,如字符型占一個字節(jié),整型占兩個字節(jié),而浮點型占四個字節(jié)。

(2)不同類型的數(shù)據(jù)在內(nèi)存中的存儲形式不同,如字符型是以ASCII碼形式存儲的,整型是以補碼形式存儲的,浮點型是以指數(shù)形式存儲的。

(3)對不同類型的數(shù)據(jù)所使用的運算符不同,比如%(求余)運算符只能用于整型變量而不能用于浮點型變量。因此變量在使用前必須先作類型聲明。3.1.5字符串常量字符串常量在C程序中有著廣泛的使用,它是用雙引號括起來的字符序列,如:“string”、“thisisabook”、“sumis%d\n”等都是字符串常量。3.1.6注解為了更好地理解程序的功能,可在適當?shù)牡胤郊幼⒔?。注解的?nèi)容放在“/*”和“*/”之間,編譯器把其中的內(nèi)容當做空白符對待而不予處理。如:

/*thisisauserdefinedfunction*/就是對一個自定義函數(shù)的注解。一個注解可以寫多行,只要注意“/*”和“*/”前后配對即可,如:

/*thisis

acomment */注意:注解不能嵌套。下面的寫法

/*thisis/*acomment*/infunction*/就是錯誤的。

【例3-1】注解的應用。/*thisisasingleprogram*/#defineTEN10#include<stdio.h>main(){intsum;sum=2*TEN+2;/*namely:sum=2*10+2;*/printf(″sum=%d\n″,sum);return0;}該程序中用到了注解和符號常量。3.2C的基本數(shù)據(jù)類型計算機可以處理多種多樣的數(shù)據(jù),這些數(shù)據(jù)有著內(nèi)在的聯(lián)系和差別。物以類聚,計算機中的數(shù)據(jù)也如此,C語言把具有某些共同特征的數(shù)據(jù)歸為一類,以便處理。

C語言作為現(xiàn)代化的語言有著豐富的數(shù)據(jù)類型,它既有基本類型,又有構(gòu)造類型,還有指針類型和空類型。圖3-1是C的數(shù)據(jù)類型總覽。圖3-1C的數(shù)據(jù)類型總覽3.2.1int(整數(shù))類型

1.int類型及其擴展對不同的數(shù)據(jù)類型,編譯系統(tǒng)會分配大小不同的內(nèi)存單元以存放某一類數(shù)據(jù),因此就決定了每一類數(shù)據(jù)必然有一定的取值范圍。整型數(shù)據(jù)是整數(shù)的一個子集。在ANSIC中,基本整型占兩個字節(jié),即16位二進制位,最高位為符號位,數(shù)值位占15位,以補碼表示。這樣它的取值范圍在機器內(nèi)部是1000000000000000~0111111111111111,大小為-215~215-1,即-32768~32767?;菊偷臉俗R符為int,由它可以定義整型變量,如

inti,j,k;則i、j、k這三個變量可以取-32768~32767之間的任何整數(shù)值。除了基本int類型之外,C語言還提供了幾種int類型的擴充形式,即在類型標識符int之前添加修飾符而形成的新的整數(shù)類型。這些修飾符為:short、long、unsigned。這樣可以擴大整數(shù)類型的取值范圍或更準確地指明取值情況。

(1)shortint:短整型,可簡寫為short。其含義為其位數(shù)不比int類型長,一般和int類型一樣長,數(shù)值范圍也為-32768~32767,在表示較小的整數(shù)時使用。

(2)longint:長整型,可簡寫為long。其含義為其位數(shù)不比int類型短,其長度規(guī)定為int類型的兩倍,即4個字節(jié),取值范圍為-231~231-1,可表示更大的整數(shù)。我們可以用sizeof運算符求出這兩種類型的長度。

【例3-2】求int、shortint和longint類型的長度。#include<stdio.h>main(){printf(″sizeof(int)=%d\n″,sizeof(int));printf(″sizeof(short)=%d\n″,sizeof(short));printf(″sizeof(long)=%d\n″,sizeof(long));return0;}程序中的sizeof是一個運算符,不是函數(shù)名。這里是要計算數(shù)據(jù)類型在內(nèi)存中所占的字節(jié)數(shù)。運行輸出:sizeof(int)=2sizeof(short)=2sizeof(long)=4因此有如下關(guān)系:

sizeof(short)≤sizeof(int)≤sizeof(long)

(3)unsignedint:無符號整型,可簡寫為unsigned。其長度和int類型相同,但是它取消了符號位,把最高位也作為數(shù)值位使用,所以它的值全部是正的。它的取值范圍為0~65535。把int類型中的0點拉到最左邊即為unsignedint類型,所以其最大值即為int型中正、負最大絕對值之和,如圖3-2所示。圖3-2int類型和unsignedint類型的取值范圍

2.整型數(shù)據(jù)的溢出上述各種整數(shù)類型都有各自的取值范圍,一旦越出了這個范圍,就不能正確地表示數(shù)據(jù),這種情況稱為“溢出”。我們先來看兩個例子。

【例3-3】整型數(shù)據(jù)的溢出一。#include<stdio.h>main(){intmax,min;max=32767;min=max+1;printf(″max=%d,min=%d\n″,max,min);

return0;}運行輸出:

max=32767,min=-32768為什么max加1以后會產(chǎn)生負值呢?這是因為整數(shù)在內(nèi)存中是以補碼形式存儲的,最高位是符號位,符號位為0時表示正數(shù),為1時表示負數(shù),而補碼運算中的符號位是參與運算的:

max:0111111111111111 + 1 min: 1000000000000000 ↑

符號位在max的最低位加1,由二進制“逢二進一”的進位規(guī)則可得到min的形式,此時符號位變?yōu)?,表示該數(shù)已變成了負數(shù),而在補碼表示的情況下,min即為十進制的-32768。

【例3-4】整型數(shù)據(jù)的溢出二。#include<stdio.h>main(){intmin,max;min=-32768;max=min-1;/*max=min+(-1);*/printf(″min=%d,max=%d\n″,min,max);return0;}運行輸出: min=-32768,max=32767我們可以作同樣的分析,在補碼表示的情況下:

1000000000000000 -32768的補碼

+ 1111111111111111 -1的補碼

10111111111111111 32767因為整型只有16位,所以最高位的進位1被舍掉了,這樣最高位(符號位)變成了0,于是也就變成了正數(shù)。由以上兩例可以看出,在int類型范圍內(nèi),正最大數(shù)加1即變?yōu)樨撟钚。撟钚p1又變成了正最大。這印證了辯證法的一個樸素真理:自然界任何事物,其發(fā)展變化都有個限度,超過這個限度就會走向反面。從上面的討論中知道,用int類型只能表示有限的整數(shù),如想表示更大范圍的數(shù),可選用其他類型,如longint或float等。比如要正確進行上例中的運算,可把max和min全部定義成longint類型。如果一個定義為longint類型,而另一個仍為int類,則運算結(jié)果仍然是不對的。

3.整型常量的幾種表示形式在C語言中,整型常量有三種表示形式:十進制表示、八進制表示和十六進制表示。對于八進制和十六進制的整型常量,其特征還表現(xiàn)在數(shù)值的前綴上。

(1)十進制表示:用十進制數(shù)碼表示數(shù),不加前綴,如123、-45、0等。

(2)八進制表示:用八進制數(shù)碼表示數(shù),加前綴“0”(數(shù)字零),如0123、0275等,而0129則為錯誤表示形式,因為9不是八進制數(shù)碼。

(3)十六進制表示:用十六進制數(shù)碼表示數(shù),加前綴0x或0X(數(shù)字零和字母x(X)),如0x1A、0X8F等。除了前綴以外,整型常量還可以帶后綴,以明確指明該數(shù)屬于什么整數(shù)類型。后綴可以是l(或L),u(或U)及其組合。l(或L)表示長整型,u(或U)表示無符號整型,組合形式有:ul、uL、Ul、UL、lu、lU、Lu、LU。例如:0x12u表示無符號十六進制,076UL表示無符號長整型八進制。整型常量加后綴主要用在函數(shù)調(diào)用中,當函數(shù)的形參是某種類型時,若能提供相應類型的實參,則會更快地運行。整型常量的類型如何確定呢?實際上,如果一個整型常量的值在某一個整型類型的取值范圍之內(nèi),那么它就可以屬于這種類型。比如123,可以認為它既是int型,又是unsignedint型,又是longint型,把它賦給這三種中任一類型的變量都是正確的;再如65330,它就不是int類型,但屬于unsignedint和longint類型;而75887則肯定只能是longint類型。不同類型的整數(shù)之間可以進行混合運算,只要能保證結(jié)果不超越相應類型的取值范圍即可。

【例3-5】不同類型整數(shù)之間的混合運算。#include<stdio.h>main(){inti;unsignedintu;longintl;i=123;u=123;l=123;printf(″i=%d,u=%d,l=%d\n″,i,u,l);i=u+l;u=l+i;printf(″i=%d,u=%d\n″,i,u);return0;}運行輸出:i=123,u=123,l=123i=246,u=3693.2.2char(字符)類型字符類型以char作為類型標識符。用char定義的變量稱為字符變量,一個字符變量只能容納一個字符。一個字符常量是用單引號括起來的字符,如′a′、′A′、′*′等。在內(nèi)存中為一個字符變量分配一個字節(jié)的存儲空間。由于一個字節(jié)的8位二進制位可以有28=256種不同的組合形式,因而可以有256個不同的字符。在這256個字符中,有些是可見的,有些是不可見的,不可見的字符只起控制作用,如換行、回車等。

1.字符在內(nèi)存中的存放形式字符在內(nèi)存中是以編碼的形式存放的。最常用的編碼方式是ASCII碼。存儲一個字符,實際上是把它的ASCII碼放入內(nèi)存中。例如:charc1,c2;c1=′a′;c2=′b′;則在內(nèi)存中:

c1:c2:因為′a′的ASCII編碼是十進制的97,二進制的01100001;′b′的ASCII編碼是十進制的98,二進制的01100010。如以十進制表示則為:c1:c2:01100001011000109798因為字符在內(nèi)存中都是以二進制形式表示的,所以字符型和整型之間有相通性,這些相通性表現(xiàn)在:

(1)字符型數(shù)據(jù)可以用整型形式輸出;反之,一定范圍內(nèi)的整數(shù)也可以用字符形式輸出。

(2)字符型變量和整型變量之間可以進行混合運算。

(3)整型變量可以接收字符常量,字符變量也可以接收整型數(shù)值,當然這都要在一定范圍之內(nèi)。這一點可由以下例子說明。

【例3-6】整型變量與字符型變量的輸出轉(zhuǎn)換。#include<stdio.h>main(){inti,j;charc1,c2;c1=′a′;c2=′b′;printf(″c1=%c,c1=%d;c2=%c,c2=%d\n″,c1,c1,c2,c2);i=97;j=98;printf(″i=%d,i=%c;j=%d,j=%c\n″,i,i,j,j);return0;}運行輸出:c1=a,c1=97;c2=b,c2=98i=97,i=a;j=98,j=b英文大小寫字母之間有這樣的關(guān)系:相應小寫字母的ASCII碼比大寫字母大32。根據(jù)這一關(guān)系,我們可以將大小寫字母任意轉(zhuǎn)換。

【例3-7】英文大、小寫字母的轉(zhuǎn)換。#include<stdio.h>main(){charc1,c2;c1=′a′;c2=′B′;printf(″c1=%c,c2=%c\n″,c1,c2);c1=c1-32;c2=c2+32;printf(″c1=%c,c2=%c\n″,c1,c2);

return0;}運行輸出:c1=a,c2=Bc1=A,c2=b

【例3-8】字符變量和整型變量互相接收對方類型的數(shù)值。#include<stdio.h>main(){inti;charc;i=′a′;c=98;printf(″i=%d,c=%d\n″,i,c);printf(″i=%c,c=%c\n″,i,c);return0;}運行輸出:i=97,c=98i=a,c=b一個字符在內(nèi)存中占一個字節(jié),對于這個字節(jié)的最高位,不同的系統(tǒng)有不同的處理方法。有的系統(tǒng)(如TurboC)就把最高位作符號位處理,因此一個字符的值就有正有負。編碼在0~127之間的字符以十進制形式輸出時為正,而編碼在128~255之間的字符以十進制形式輸出時為負。所以定義:

charch;就相當于:

signedcharch;為了在以%d形式輸出字符時不出現(xiàn)負值,可以把字符定義成無符號字符:

unsignedcharch;對編碼在128~255之間的字符,不管是以char定義,還是以unsignedchar類型定義,它們在以字符輸出格式%c輸出時都是擴展的ASCII碼表中的字符。

【例3-9】字符輸出一。#include<stdio.h>main(){charc=199;printf(″c=%d,c=%c\n″,c,c);return0;}輸出為:

c=-57,c=‖-

【例3-10】字符輸出二。#include<stdio.h>main(){unsignedcharc=199;printf(″c=%d,c=%c\n″,c,c);return0;}輸出為:

c=199,c=‖-

2.字符常量我們已知字符常量是用單引號括起來的字符,這對于可顯示字符來說很容易表示,但對于控制字符怎樣表示呢?在C語言中沒有相應的直接形式顯示這些字符,但可以換一種形式來表示它們,即用轉(zhuǎn)義字符來表示。轉(zhuǎn)義字符是以反斜杠′\′開頭,后面加其他字符。反斜杠的作用是把后面的字符賦以新的含義(即轉(zhuǎn)義)。以′\′開頭定義的字符有三種情況:非顯示字符(控制字符)、可顯示字符和字符的數(shù)值表示,如表3-1所示。

【例3-11】轉(zhuǎn)義字符的輸出。#include<stdio.h>main(){printf(″Thisisaprogram\n″);printf(″\thisis\ba\012program\n″);printf(″\″first\\second\″″);return0;}運行輸出:Thisisaprogramhisiaprogram″first\second″其中,“\t”是水平制表符,“\b”是退格符,“\012”和“\n”都是換行符。要想輸出“\”,必須寫成“\\”;要想輸出“"”,必須寫成“\"”。

3.字符和字符串前面已指出,字符串是用雙引號括起來的字符序列。字符和字符串有著本質(zhì)的區(qū)別:

(1)字符用單引號括起來,而字符串用雙引號括起來。

(2)單引號括起來的只有一個字符,而雙引號括起來的有多個字符。不管顯示出來的有多少個字符,字符串都由一個看不見的字符′\0′結(jié)束,因此′a′和″a″并不相同。前者是字符,后者是字符串,″a″中有兩個字符:′a′和′\0′。′\0′是ASCII碼值為0的字符,是“空字符”。C語言規(guī)定,字符串必須以′\0′結(jié)束,這個字符是系統(tǒng)自動加上去的,不是顯式輸入的。系統(tǒng)據(jù)此可以判斷字符串是否結(jié)束。因此″a″在內(nèi)存中的形式是a\0它占有兩個字節(jié),長度為2,而′a′的長度為1。因此如果有定義:

charc;則

c=″a″;就是錯誤的。3.2.3float和double類型通常稱float為浮點類型,而稱double為雙精度類型,它們都用來表示實數(shù),差別只在于長短不同,因而所能表示的數(shù)的范圍也不同。

1.浮點型數(shù)據(jù)的兩種表示形式對于一個實型常量,可以用兩種形式表示它,即十進制小數(shù)形式和指數(shù)形式。

(1)十進制小數(shù)形式,如123.45、-0.001。

(2)指數(shù)形式,其組成格式為:

〈尾數(shù)部分〉e(或E)〈指數(shù)部分〉其含義為:

〈尾數(shù)部分〉×10〈指數(shù)部分〉這幾部分的書寫規(guī)則是:①尾數(shù)部分不能省略,即e(或E)前必須有數(shù)據(jù)。②指數(shù)部分必須是整數(shù)。③尾數(shù)可以只有整數(shù)部分或只有小數(shù)部分。④指數(shù)、尾數(shù)都可以帶符號,如省略符號則隱含為正。例如:123e2、1.23E4、.123e5、123000E-1等都是正確的書寫形式,且代表同一個數(shù)12300;而3E22.5、-e-3等都是錯誤的指數(shù)形式。雖然同一個實數(shù)的指數(shù)形式可以有多種,但只有一種形式是規(guī)格化的,即尾數(shù)部分只有一位整數(shù)的形式,如1.23e4。浮點型數(shù)據(jù)在內(nèi)存中也是按指數(shù)形式存儲的。對于有4個字節(jié)32位的實型數(shù)據(jù),一般情況是尾數(shù)部分24位,指數(shù)部分8位,其中各含一位符號位,即

2.浮點型變量的分類浮點型變量分單精度(float)、雙精度(double)和長雙精度(longdouble)三種,它們的長度、精度及取值范圍如表3-2所示。在ANSIC中,浮點常量被默認為double類型,如果要顯式地指明某浮點數(shù)為float類型,必須加上后綴f或F,如1.6f、3.7F等。在不需要太大的精度時,這種表示可以加快運算速度,節(jié)省內(nèi)存空間。3.2.4變量賦初值前面已介紹了三種數(shù)據(jù)類型,用類型名可以定義相應的變量。根據(jù)先定義后使用的原則,在定義變量之后,可以對它進行處理。如:inti,j;i=3;j=3;通過賦值語句,使i、j具有數(shù)值3。我們還可以把二者結(jié)合起來,即在定義變量的同時就讓它有一個值,這就是變量賦初值,如:

inti=3,j=3;程序可以對i、j的當前值進行運算,當然這些值在以后是可以改變的。注意:上面的語句中變量i和j都具有初始值3,能不能把它們連寫呢?如:

inti=j=3;答案是:這樣寫是錯誤的,只能對它們分別賦初值,即使這些初值都是相同的也不能連寫。要使i、j具有相同的值,還可以采用下面的方法:

inti,j; i=j=3;這種寫法是合法的,但這和賦初值的含義是不同的??梢远x多個變量而對其中個別變量賦初值:

inti,j=3;則j具有初值3,而i未賦初值,即它的值是不確定的,不能直接使用。3.3C的運算符及表達式

C語言不僅數(shù)據(jù)類型豐富,運算符也十分豐富,幾乎所有的操作都可作為運算符處理。由運算符加適當?shù)倪\算對象可構(gòu)成表達式,而表達式是C程序的重要要素之一,因此掌握好運算符的使用對編寫程序是十分重要的。對于每一個運算符,要注意從兩個方面去把握:運算符的優(yōu)先級和結(jié)合性。優(yōu)先級指多個運算符用在同一個表達式中時先進行什么運算,后進行什么運算;而結(jié)合性是指運算符所需要的數(shù)據(jù)是從其左邊開始取還是從右邊開始取,因而有所謂“左結(jié)合”和“右結(jié)合”之說。本章中我們介紹一些最基本的運算符,后面的章節(jié)中將陸續(xù)介紹其他運算符。3.3.1算術(shù)運算符

1.基本的算術(shù)運算符

C語言中基本的算術(shù)運算符有:+、-、*、/、%,其含義如表3-3所示。

在算術(shù)運算符的使用中有以下兩點需要注意:

(1)除法運算符“/”的結(jié)果和其運算對象有關(guān)。如果兩個運算對象都是符號相同的整數(shù),則運算符“/”的功能是整除,結(jié)果為整數(shù)。整除的含義是舍去小數(shù)部分,只保留整數(shù)部分。兩個運算對象中如果有一個是浮點數(shù),則結(jié)果就是浮點數(shù)。如果兩個運算對象都是整數(shù),但其中有一個是負數(shù),另一個是正數(shù),則一般采用“向零取整”的原則,即按其絕對值相除后再加負號。還應注意,在做除法運算時,除數(shù)不能為0。如除數(shù)為0,則會導致致命錯誤而使程序以失敗終止。

(2)求模運算符“%”要求其運算對象都必須是整數(shù),但可正可負。對有負數(shù)情況的處理有以下一般性的原則:先按其絕對值求模(|r|%|s|),然后取被除數(shù)r的符號作為模的符號。

【例3-12】算術(shù)運算的輸出。#include<stdio.h>main(){printf(″5/3=%d,-5/+3=%d\n″,5/3,-5/+3);printf(″3/5=%d,3./5=%f\n″,3/5,3./5);printf(″10%%3=%d,-10%%3=%d,10%%-3=%d,-10%%-3=%d\n″,10%3,-10%3,10%-3,-10%-3);return0;}運行輸出:5/3=1,-5/+3=-13/5=0,3./5=0.60000010%3=1,-10%3=-1,10%-3=1,-10%-3=-1由例3-12可知,要輸出一個“%”,在字符串中必須有兩個“%”,即“%%”。

2.算術(shù)運算符的優(yōu)先級和結(jié)合性

C語言中算術(shù)運算符的優(yōu)先級和代數(shù)中的規(guī)定是一樣的,并且都是從左向右結(jié)合的,如表3-4所示。例如,有代數(shù)表達式:

z=bp-r%-q+((a+b)c)÷x-y將其轉(zhuǎn)變成C語言表達式為

z=b*p-r%-

q+((a+b)*c)/x-

y ①④③②⑧⑤⑥⑦⑨則運算時將按①、②、…⑧、⑨所示的順序進行。其中,q前的“-”號為單目運算符,優(yōu)先級最高,而r前的“-”是代表減運算。如何加以區(qū)分呢?凡+、-號前沒有數(shù)字或只有*、/、%等級別較高的運算符時,“+”、“-”即為單目運算符,否則即為加、減運算符。3.3.2自加(++)自減(--)運算符

C語言中有兩個特殊的算術(shù)運算符,即自加、自減運算符(++和--)。這兩個運算符都是單目運算符,它們既可以放在運算對象之前,也可以放在運算對象之后,形成前置形式和后置形式,而運算對象也只能是整型變量。不管前置還是后置,其運算結(jié)果都是一樣的,都是把運算對象的值增加1或減少1。設(shè)有整型變量i,則++i、i++都使i值增加1,--i、i--都使i值減少1。既然效果相同,那么區(qū)分前置和后置形式又有何意義呢?其意義不在于它所作用的變量本身,而在于對變量值的使用。前置形式是先把變量值加(減)1,然后用新的值參與表達式的運算;而后置形式是先用變量的原始值參與表達式的運算,然后再對變量的值加(減)1。例如有語句:

inti,j=2;則下面運算的結(jié)果是i等于3,j也等于3:

i=++j;而下面的運算結(jié)果是i等于2,而j等于3:

i=j++;

使用自加、自減運算符應注意以下幾點:

(1)最常見的錯誤是把自加、自減運算符用在非簡單整型變量的表達式上,如++(x+2)、++(-i)等都是錯誤的。

(2)自加自減運算符的結(jié)合性為:前置時是自右向左的,后置時是自左向右的。比如p=-x++等價于p=-(x++)。這個表達式的意思是先用x變量的當前值加負號賦給p,而后x再加1。該表達式并不等價于p=(-x)++,因為這樣就使++作用在表達式-x上了,這是(1)中指出的錯誤。

(3)如果兩個運算對象之間連續(xù)出現(xiàn)多個運算符,則C語言采用“最長匹配”原則,即在保證有意義的前提下,從左到右盡可能多地將字符組成一個運算符。因此i+++j就被解釋成(i++)+j而不是i+(++j)。同樣,i++++j被解釋成(i++)++j;i+++++j被解釋成((i++)++)+j。而這兩種情況都是錯誤的。正確的寫法應該是在連續(xù)的運算符中間的適當?shù)胤皆黾涌崭穹指舴蚣永ㄌ?,使分開的部分成為有意義的運算對象。比如應把i+++++j寫成i+++++j或(i++)+(++j)。

(4)對所有簡單類型的變量都可以進行自加、自減運算。

【例3-13】自加運算。#include<stdio.h>main(){intp,x=3;charc=′a′;

floatf=3.2;p=-x+++1;

printf(″p=%d,x=%d\n″,p,x);printf(″c=%c\n″,++c);printf(″f=%f\n″,++f);return0;}運行輸出:p=-2,x=4c=bf=4.200000

(5)ANSIC并沒有規(guī)定所有運算符操作數(shù)的計算順序。例如對于語句:i=m*n+p*q;,根據(jù)運算符的優(yōu)先級和結(jié)合性可知,它等同于i=(m*n)+(p*q);,但對于m*n和p*q誰先進行計算,C并未明確規(guī)定,不同的編譯系統(tǒng)都有不同的規(guī)定。因此在一個語句中如果要對一個變量前后使用多次,而且前后值不同,則應避免使用自增、自減運算符。比如:

i=1; m=++i*(i+1);對于這個表達式,編譯系統(tǒng)可能:①先計算++i,再計算i+1;②先計算i+1,后計算++i。對于①,結(jié)果是m=2*(2+1)=6;而對于②,結(jié)果是m=2*(1+1)=4。為避免產(chǎn)生這種二義性,應當把它們分成兩個表達式,明晰地表達程序員的意圖。如果想得到①的結(jié)果,可寫成:++i;m=i*(i+1)如果想得到②的結(jié)果,可寫成:j=i+1;m=j*(i+1);i++;另外,在一個表達式中若同一個變量前后出現(xiàn)多次并且還被施以自加運算,則這樣的表達式的運算結(jié)果還會因變量出現(xiàn)地點的不同而不同。如inti=5,j;j=i+++i+++i++;printf(″j=%d\n″,j);printf(″i=%d\n″,i);則結(jié)果為

j=15i=8這里,表達式中的三個i都以其初值5參與運算,相當于5+5+5。而將該表達式作為printf()函數(shù)的參數(shù)時,就會出現(xiàn)不同的情況:inti=5;printf(″sum=%d\n″,i+++i+++i++);printf(″i=%d\n″,i);則結(jié)果為sum=18i=8在作為函數(shù)參數(shù)的表達式中,每個參與運算的i的值都是不同的,第一個i以其初值5參與運算,同時進行++運算,使其值變?yōu)?,作為第二個i的值參與運算。同樣再進行++運算后,使其值變?yōu)?,作為第三個i的值參與運算,相當于5+6+7。編寫程序應當使用通用的規(guī)則,把可讀性放在第一位,不要使用依賴于不同編譯系統(tǒng)的規(guī)則去編寫那些晦澀難懂、令人捉摸不定的程序,因此不要去編寫(i++)+(i++)+(i++)以及printf(″%d,%d″,i,i++);這樣的表達式和語句。3.3.3關(guān)系及邏輯運算符關(guān)系運算符用來比較兩個運算對象的大小,比較的結(jié)果是真和假兩個邏輯值,而邏輯運算符的操作對象和結(jié)果也都是邏輯值,因此這兩種運算符在使用時有著密切的聯(lián)系。

1.關(guān)系運算符關(guān)系運算符又分為兩類:相等判斷運算符和不相等判斷運算符,它們分別是:

(1)不相等判斷運算符:>(大于)、>=(大于等于)、<(小于)、<=(小于等于);

(2)相等判斷運算符:==(等于)、!=(不等于)。關(guān)系運算符的優(yōu)先級低于算術(shù)運算符,而在其內(nèi)部,不相等判斷又高于相等判斷,但它們都高于賦值運算符。關(guān)系運算符的結(jié)合性是從左向右的。兩個對象比較的結(jié)果是真或假這兩個邏輯值之一,它們在C語言中是這樣表示的:數(shù)字0表示假,非0表示真,比如1、4、′a′等都表示真,這似乎是不可確定的,但關(guān)系運算產(chǎn)生的結(jié)果都是確定的,真就是1,而不是別的值。

【例3-14】關(guān)系運算符。#include<stdio.h>main(){inta,b,c;a=b=c=10;a=b==c;printf(″a=%d,b=%d,c=%d\n″,a,b,c);printf(″a==(…):%d\n″,a==(b=c++*2));printf(″a=%d,b=%d,c=%d\n″,a,b,c);a=b++>=++b>c++;printf(″a=%d,b=%d,c=%d\n″,a,b,c);return0;}運行輸出:a=1,b=10,c=10a==(…):0a=1,b=20,c=11a=0,b=22,c=12第二個printf語句輸出的是一個比較結(jié)果,比較運算符右邊的運算對象又是個復雜的運算,結(jié)果b、c的值都有改變,這反映在第三個printf語句中。在a=b++>=++b>c++中,按照運算符的優(yōu)先級和結(jié)合性,先進行賦值號右邊的運算。首先做b++和++b的大于等于(>=)比較,把比較的結(jié)果(1或0)再和c++進行大于(>)比較,最后把比較的結(jié)果賦給a。在b++>=++b中,先把第一個b的值(20)作為和后面比較的數(shù)據(jù),同時它的值又自動加1變成了21,第二個b值是在21的基礎(chǔ)上再進行自加運算,因而其值為22。對于由兩個字符構(gòu)成的比較運算符,在使用中常見的錯誤是:

(1)把兩個字符的次序?qū)戭嵉?,?gt;=、!=、<=寫成=>、=!、=<。

(2)在兩個字符之間加空格,把>=、!=、<=、==寫成>=、!=、<=、==。今后凡是由兩個以上字符構(gòu)成的運算符,在使用中都要注意防止出現(xiàn)上面兩種錯誤。

(3)把相等運算符誤寫成賦值運算符,即把==寫成=,這也是初學者常犯的錯誤。

2.邏輯運算符

C語言提供了三個邏輯運算符,按由高到低的優(yōu)先級次序排列如下:

! 邏輯非(把邏輯值進行翻轉(zhuǎn),相當于NOT) && 邏輯與(求兩個邏輯值的與,相當于乘運算AND) ‖ 邏輯或(求兩個邏輯值的或,相當于加運算OR)其中,!為單目運算符,&&、‖為雙目運算符,其功能和用法可由表3-5的真值表說明。表中,e1、e2為邏輯表達式或關(guān)系表達式,具有0或非0的值。前已指出,可以用非0來表示真,不一定是1,但是在用邏輯運算符作用后,就一定是0或1了。比如3&&′a′‖0的結(jié)果為1,!5的結(jié)果為0。注意:如再對!5求非,!(!5)的值是1而不是5,因此在一般情況下,當x不是0或1時,!!x不等于x。我們可以把到目前為止我們見過的運算符放在一塊,這樣可以查看其在優(yōu)先級中所處的位置,如圖3-3所示。邏輯運算符的結(jié)合性:除!是右結(jié)合外,&&和‖均為左結(jié)合,如!!x等于!(!x),a‖b‖c等于(a‖b)‖c。程序中使用關(guān)系運算符時要注意返回結(jié)果是用0、1來表示真假值的,不要用常規(guī)的數(shù)學知識去思考和理解。圖3-3運算符的優(yōu)先級!(非)高算術(shù)運算符關(guān)系運算符

&&(與)‖(或)=(賦值)低

【例3-15】邏輯運算符一。#include<stdio.h>main(){inti=7,m,n;m=!!i;n=(3<i<6);printf(″i=%d,m=%d,n=%d\n″,i,m,n);return0;}運行輸出:

i=7,m=1,n=1雖然經(jīng)過!!i運算,但i本身的值并沒有改變,它返回給m的只是個中間結(jié)果。!!i=!(!7)=!0=1,所以m值是1;3<i<6即3<7<6,從數(shù)學上看這個不等式的結(jié)果應是假的,但在C語言中卻是這樣處理的:

(3<i<6)=((3<i)<6)=(1<6)=1事實上,在這里不論i為何值,3<i的結(jié)果一定是0或1,它們都小于6,因此最后的結(jié)果為1,這就是n的值。根據(jù)邏輯運算符&&和‖的功能及結(jié)合性,對邏輯表達式進行求值的時候,常用所謂的“懶惰求值法”,即只要能判斷出邏輯表達式的真假即停止向后進行運算?!皯卸枨笾捣ā敝饕福?/p>

(1)a&&b&&c:當求得a值為假時即停止對b、c的求值,因為此時已可斷定整個表達式為假了;只有當a為真時才去求b,只有當a、b全為真時才去求c。

(2)a‖b‖c:當求得a值為真時即停止對b、c的求值,因為此時已可斷定整個表達式為真了;只有當a為假時才去求b,只有當a、b皆假時才去求c。

【例3-16】邏輯運算符二。#include<stdio.h>main(){inta,b,c;a=b=c=1;++a‖++b&&++c;printf(″(1)a=%d,b=%d,c=%d\n″,a,b,c);a=b=c=1;++a&&++b‖++c;printf(″(2)a=%d,b=%d,c=%d\n″,a,b,c);a=b=c=1;++a&&++b&&++c;printf(″(3)a=%d,b=%d,c=%d\n″,a,b,c);a=b=c=-1++a&&++b‖++c;printf(″(4)a=%d,b=%d,c=%d\n″,a,b,c);a=b=c=-1;++a‖++b&&++c;printf(″(5)a=%d,b=%d,c=%d\n″,a,b,c);a=b=c=-1;++a&&++b&&++c;printf(″(6)a=%d,b=%d,c=%d\n″,a,b,c);return0;}運行輸出:(1)a=2,b=1,c=1(2)a=2,b=2,c=1(3)a=2,b=2,c=2(4)a=0,b=-1,c=0(5)a=0,b=0,c=-1(6)a=0,b=-1,c=-1

注意:輸出(4)是求++a&&++b‖++c,++a等于0僅說明不需要求b就可知++a&&++b為假,但還不能說整個表達式為假,還必須對‖后面的++c進行運算。因為‖和&&都是嚴格地按從左到右的順序進行運算的,即使它們出現(xiàn)在同一個表達式中也是如此,當‖出現(xiàn)在&&之前時,也不會因為&&的優(yōu)先級高而先對&&的運算對象進行運算,因此++a‖++b&&++c等同于++a‖(++b&&++c),所以有(1)和(5)的輸出結(jié)果。由關(guān)系運算符和邏輯運算符可以表示復雜的邏輯條件,這在程序設(shè)計中是經(jīng)常用到的。比如要表示某一年份year是否為閏年,根據(jù)天文學知識,只要符合下列條件之一即為閏年:

(1)年份year能被4整除,但不能被100整除;

(2)年份year能被400整除。據(jù)此可以寫出邏輯表達式:

(year%4==0&&year%100!=0)‖year%400==0根據(jù)運算符的優(yōu)先級,式中的括號是可以不要的,加上是為了清晰。3.3.4賦值運算符要使一個變量得到值或改變它的值,除了可以用scanf函數(shù)輸入外,也可以很方便地用賦值運算符實現(xiàn)。前面我們已介紹過賦值運算符的基本使用,現(xiàn)在做進一步的說明。

1.一般的賦值運算符在C語言中,賦值運算符為=,由它可以構(gòu)成賦值表達式:

〈變量名〉=〈表達式〉賦值運算就是首先計算右邊表達式的值,然后把它賦給左邊的變量。賦值表達式的值就是左邊變量最后的值。如表達式a=1和b=′a′+1,a、b的值分別是1和98。賦值運算符右邊的表達式本身又可能是賦值表達式,也就是說賦值表達式可以遞歸定義,于是就可以出現(xiàn)a=b=c=10這樣的寫法。如何分析這種形式呢?這涉及到賦值運算符的結(jié)合性問題。賦值運算符是右結(jié)合的,因此a=b=c=10等價于a=(b=(c=10))。最右邊的賦值運算使c的值為10,它也是這個小表達式的值,把這個值再賦給b,它的值10也是右邊第二個賦值表達式的值,最后再把這個值賦給a,a的值為10,這也是整個表達式的值。作為過程結(jié)果,a、b、c的值都是10,就像是把最右邊表達式的值連續(xù)地賦給了它左邊的各個變量一樣。賦值號兩邊的部分分別稱為“左值”和“右值”,只有變量才能充當左值,非簡單變量的表達式不能作左值使用。因此,a++=1;、a=b++=c++=2;等都是錯誤的。但++a=1;卻是正確的,因為這是先對a進行加1運算,其值增加1,它本身仍然是個變量,所以可以充當左值;而a++相當于a+1,已不是個簡單變量了,所以不能作左值。賦值操作也是一種破壞性輸入,即不管左邊變量原來具有什么樣的值,結(jié)果都要變成右邊表達式的值。如:inta=5,b=6;a=b+3;b=a-2;a,b的初值分別是5和6,但經(jīng)過賦值運算之后,a和b的值分別變?yōu)?和7。賦值運算符的優(yōu)先級是除逗號運算符之外最低的。

2.賦值運算中的類型轉(zhuǎn)換如果賦值運算符兩邊的類型不一致,則在賦值的時候要對右邊表達式的類型進行轉(zhuǎn)換,使之適應左邊變量的要求,或者說用左邊變量的類型去剪裁改造右邊的表達式。為了便于表達,我們做如下的約定: [類型1]←(類型2)表示把類型2的值賦給類型1的變量。具體地有以下幾種情況:

(1)[int]←(float,double):此時去掉實數(shù)的小數(shù)部分,只把其整數(shù)部分賦給整型變量。如:

inti=9.87;結(jié)果i中只有整數(shù)9,舍掉的小數(shù)部分并不進行四舍五入處理。

(2)[float]←(int)和[double]←(int):變量中的整數(shù)部分是右邊表達式的值,而小數(shù)部分是相應個數(shù)的

0。如:

floatf=15; doubled=15;則有:

f=15.000000(6個0) d=15.00…0(14個0)

(3)[float]←(double):在float類型所能容納的范圍之內(nèi),把double數(shù)值的前7位放入float型變量中,超過范圍則出錯。[double]←(float):在double變量中,有效位數(shù)擴展到16位,數(shù)值不變。

(4)[int]←(unsignedchar):int類型占兩個字節(jié),char類型占一個字節(jié),賦值時把字符放入整型變量的低8位,高8位全補0,以保證是正整數(shù)。例如:

inti;unsignedcharc=′\376′;i=c;則其內(nèi)存表示為:[int]←(char):是把有符號的字符賦給整型變量。這時,如字符符號位是0,則整數(shù)的高8位全補0;如字符符號位是1,則整數(shù)高8位全補1,這稱為“符號擴展”,目的是為了保證賦值后的數(shù)值保持不變。再如:

inti;charc=′\376′;i=c;則賦值后的內(nèi)存結(jié)果為之所以要采用符號擴展的原則,是為了保證在以十進制整數(shù)格式%d輸出i和c時,它們都具有相同的值-2。

(5)[char]←(int,shortint,longint):只把整數(shù)的低8位送到字符變量中,其余全部截掉,當整數(shù)大于255(低8位的最大值)時,賦值在變量中會改變原來的值,如:

inti=256;charc;c=i; printf(″i=%d,c=%d\n″,i,c);則輸出為

i=256,c=0內(nèi)存表示為

(6)[long]←(int):把int類型數(shù)值送入long類型的低16位中,高16位按“符號擴展”的原則處理。 [int]←(long):把long的低16位送入int型變量,高16位截掉,如高16位中仍有數(shù)據(jù),則賦值在變量中有可能改變原來的值。

(7)[int]←(unsignedint)、[long]←(unsignedlong)及[short]←(unsignedshort):這類賦值的特點是兩邊的長度相等,但取值范圍不同,右邊的正數(shù)范圍要比左邊大一倍,因此只有在左邊的正數(shù)范圍內(nèi)賦值才正確,否則所賦的正值在變量中會得到負的結(jié)果。例如:intb;unsignedinta=65535;b=a;printf(″a=%u,b=%d\n″,a,b);結(jié)果為a=65535,b=-1內(nèi)存表示為

(8)[unsignedin]←(int)、[unsignedlong]←(long)及[unsignedshort]←(short):這是和(7)相反的賦值,可以照原值全部傳送,但若傳送負數(shù),則接收者會得到一個正數(shù)的結(jié)果,其原因在于把原來的符號位也當成了數(shù)值位。例如:unsignedinta;intb=-1;a=b;printf(″b=%d,a=%u\n″,b,a);則輸出為

b=-1,a=65535內(nèi)存表示為

3.復合的賦值運算符在普通賦值運算符的前面加上其他成分,可構(gòu)成復合的賦值運算符。其一般形式是:

〈變量名〉@=〈表達式〉其中,@可以是如下運算符之一:+、-、*、/、%、、、&、|、^。前5個是算術(shù)運算符,后5個是位運算符(將在后面章節(jié)中介紹)。復合賦值運算的語義是:

〈變量名〉=〈變量名〉@(〈表達式〉)即把變量的原值和表達式的值進行由@指出的運算,再把運算結(jié)果賦給變量。如設(shè)a的初值為3,則a*=6就等價于a=a*6,即a的終值為18。因此這里要求變量一定要具有初值,如沒有初值,則放入復合賦值運算表達式中就是錯誤的。

注意:

在把復合賦值形式轉(zhuǎn)換成普通賦值形式時,對原表達式最好加括號,否則有可能出錯。如:

x*=y+4;這種寫法是正確的,但當把它變成普通形式而對表達式y(tǒng)+4不加括號時會變成:

x=x*y+4;這就和原意大相徑庭了。應該寫成:

x=x*(y+4);這樣才正確。在有多個復合賦值的表達式中,要時刻注意變量的當前值,并且當前所考慮的復合賦值運算符兩邊的同一變量應該具有相同的值。例如,設(shè)a=8,求a+=a-=a*a的結(jié)果。根據(jù)賦值運算符右結(jié)合的特點,原式等價于:a+=(a=a-(a*a)),計算最右邊的算術(shù)表達式后得:a+=(a=-56),此時+=兩邊的a應該以共同的新值-56參與運算,而不再是原來的8了。于是變?yōu)椋篴=a+a=-56-56=-112。這是正確的結(jié)果,而不要理解成:a=8-56=-48。當作為左值的變量有前置的++、--運算符時,則先對變量進行自加、自減運算,再將運算結(jié)果和右邊的表達式進行相應運算。如a=8,則++a+=1就相當于a=(++a)+1=9+1=10。3.3.5逗號運算符逗號在C語言中主要起兩個作用,一個是作為分隔符,一個是作為運算符。

1.逗號分隔符把兩個對象分開可以用多種符號,如空格、反斜杠等,但多用逗號作分隔符。在變量的定義和函數(shù)的參數(shù)中都用到了逗號分隔符。如:

inti,j,k;charc1,c2,c3; result=max(a,b);這里它的作用是把同類型的變量名分開,把函數(shù)的各個參數(shù)分開。

2.逗號運算符作為運算符,它是把兩個對象“連接起來”,使之成為一個逗號表達式。其一般形式是:

〈表達式1〉,〈表達式2〉,…,〈表達式n〉例如:

i=1,j=0,sum=0,m=2*i+3是一個由四個賦值表達式構(gòu)成的逗號表達式。逗號運算符的優(yōu)先級是最低的,它的結(jié)合性是從左向右的。因此在求表達式的值時,是從左向右進行計算的,后面表達式的計算可以利用前面表達式的計算結(jié)果,而最后那個表達式的值就作為整個表達式的值,其類型也是整個表達式的類型。因此上面的逗號表達式是先對i=1計算,求出i的值用于后面表達式的計算,即求出m=5,這也是整個逗號表達式的值。3.3.6sizeof運算符

sizeof是一個單目運算符,其作用是求運算對象所具有的字節(jié)數(shù)。它的使用形式是:

sizeof(〈運算對象〉)或sizeof〈運算對象〉其中,運算對象可以是數(shù)據(jù)類型名、變量名、常量名等。變量、常量的大小實際上是它所屬類型的大小。在求字符串常量的大小時,包括了看不見的符號′\0′。若運算對象是類型名或由運算符連成的表達式,則必須用括號括起來;如果運算對象是簡單常量或變量,則括與不括均可,如sizeofi++也是合法的,但最好加上括號。

sizeof運算符僅求其對象的長度,并不對運算對象進行求值計算,比如sizeof(++i)并不對i進行自加運算。

【例3-17】sizeof運算符。#include<stdio.h>main(){inti=162;floaty=0.0;printf(″sizeof(++i)=%d,i=%d\n″,sizeof(++i),i);printf(″sizeof(162)=%d\n″,sizeof(162));printf(″sizeof(\″China\″)=%d\n″,sizeof(″China″));printf(″sizeof(int)=%d\n″,sizeof(int));printf(″sizeof(float)=%d\n″,sizeof(float));printf(″sizeof(double)=%d\n″,sizeof(double));printf(″sizeof(1.1)=%d\n″,sizeof(1.1));printf(″sizeof(y=2*i+6.0)=%d\n″,sizeof(y=2*i+6.0));

printf(″y=%f\n″,y);return0;}運行輸出:sizeof(++i)=2,i=162sizeof(162)=2sizeof(″China″)=6sizeof(int)=2sizeof(float)=4sizeof(double)=8sizeof(1.1)=8sizeof(y=2*i+6.0)=4y=0.000000因為考慮到了′\0′,所以sizeof(″China″)=6。編譯程序總是把浮點常數(shù)作為double類型來處理,因此有sizeof(1.1)=8。

sizeof(y=2*i+6.0)=4是因為賦值運算符的左值y的類型是float,占4字節(jié),返回的是y的類型的長度。

y=0.000000表明sizeof運算并不對運算對象求值。

雖然sizeof的使用像是一個函數(shù)調(diào)用,但它只是個運算符,不是函數(shù),它沒有函數(shù)調(diào)用方面的開銷。3.3.7條件運算符條件運算符“?:”是C語言中惟一的一個三目運算符,它有三個運算對象,分別由“?”和“:”把它們連接起來,構(gòu)成一個條件表達式。其語法形式是:

〈表達式1〉?〈表達式2〉:〈表達式3〉它的語義如圖3-4所示。圖3-4條件運算符的語義整個條件表達式的值要么是表達式2的值,要么是表達式3的值,全依賴于對表達式1的求值而定。表達式1是條件表達式,具有真假兩個值,如其值為真,則計算表達式2,并把表達式2的值作為整個表達式的值返回;如其值為假,則把表達式3的求值結(jié)果返回。條件表達式可以嵌套和遞歸定義,在這種情況下,應先找到?和:,把它的三部分區(qū)別出來,然后按一般方法進行計算求值。條件運算符的結(jié)合性是由右向左的。例如:

a>b?a:c>d?c:d等價于

a>b?a:(c>d?c:d)條件運算符的優(yōu)先級高于賦值運算符而低于關(guān)系運算符和算術(shù)運算符。因此

max=a>b?a:b+1;等價于

max=(a>b)?a:(b+1);而不等價于max=(a>b?a:b)+1;條件表達式中的三個表達式的類型可以互不相同,條件表達式的類型為表達式2和表達式3二者中較高的類型。忽視了這一點,程序就會出現(xiàn)錯誤的結(jié)果。

【例3-18】條件運算符一。#include<stdio.h>main(){intx=10;floaty=5;printf(″%d\n″,x>y?x:y);

return0;}本來預期輸出應該是10,但結(jié)果卻是0。這是因為在條件表達式“x>y?x:y”中,y的類型高,因此整個表達式的類型就應該是y的類型float,而對float類型數(shù)據(jù)用′%d′控制符是輸出不了結(jié)果的。如果把′%d′換成′%f′,則會顯示出正確的結(jié)果:10.000000。

【例3-19】條件運算符二。#include<stdio.h>main(){inta,b,c;a=b=c=1;a+=b;b+=c;c+=a;printf(″(1)%d\n″,a++>b?a:b);printf(″(2)%d\n″,a>b?c>a++:b-->a?c++:c--);(a>=b>=c)?printf(″AA\n″):printf(″BB\n″);printf(″a=%d,b=%d,c=%d\n″,a,b,c);return0;}運行輸出:

(1)2 (2)0 BB a=4,b=2,c=3由復合賦值運算得:a=2,b=2,c=3,在計算a++>b?a:b中的a++>b為假之后,a就變成了3。表達式

a>b?c>a++:b-->a?c++:c--等價于

a>b?c>a++:(b-->a?c++:c--)右結(jié)合的規(guī)則使最右邊的條件表達式成為一個整體,但這是否意味著先對它進行計算呢?答案是否定的。因為?:、‖、&&和,這四個運算符都嚴格地按從左向右的順序進行運算,所以還是先計算a>b的值,而不是先計算b-->a的值。從上面還可以看出:條件表達式中的表達式2和表達式

溫馨提示

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

評論

0/150

提交評論