當前位置:首頁 » 編程語言 » 復合形法c語言
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

復合形法c語言

發布時間: 2023-01-13 19:50:51

㈠ 復合語句在語法上被稱為是____,空句的形式是_____. c語言的問題

空語句 只是一個分號。
如下:
;

㈡ c語言中空語句的一般形式是為,還有復合語句的形式為。50分。好好回答。謝謝,非專業勿擾

只有分號「;」組成的語句稱為空語句。

空語句是什麼也不執行的語句。在程序中空語句可用來作空循環體。

例如:while(getchar()!=' ');本語句的功能是,只要從鍵盤輸入的字元不是回車則重新輸入。這里的循環體為空語句。

復合語句從形式上看是多個語句的組合,但在語法意義上它是一個整體,相當於一條語句,所以凡是可以用簡單語句的地方都可以用復合語句來實現。在程序設計中復合語句被看成是一條語句,而不是多條語句。

例如:

{a=10;printf(「%d」,a);}

就是復合語句。變數a=10的作用區域就在{ }之內,用於printf函數的輸出處理。詳細內容見變數的存儲類別。

提示 復合語句中的每一條語句都必須以「;」結束。而不允許將「;」寫在「}」外。復合語句不需要以「;」結束。

(2)復合形法c語言擴展閱讀:

空語句實際上並不能執行任何語句,對於程序員來說是沒有意義的。但由於編程語言的規范性,例如在某種特殊情況下,希望使用三目運算符但只希望判斷正確或錯誤時返回結果,否則不做任何事,在沒有空語句填充三目運算符間的空缺的話,程序是會報錯的。此時空語句則非常必要。

在程序中空語句可用來作空循環體,例如:while(getchar()!=' ');或:while(getchar()!=' '){}

㈢ C語言基礎知識

  •1 C語言程序的結構認識

用一個簡單的c程序例子,介紹c語言的基本構成、格式、以及良好的書寫風格,使讀者對c語言有個初步認識。

例1 計算兩個整數之和的c程序:

1、任何一個c語言程序都必須包括以下格式:

這是c語言的基本結構,任何一個程序都必須包含這個機構。括弧內可以不寫任何內容,那麼該程序將不執行任何結果。

2、main()----在c語言中稱之為「主函數」,一個c程序有且僅有一個main函數,任何一個c程序總是從main函數開始執行,main函數後面的一對圓括弧不能省略。

3、被大括弧{ }括起來的內容稱為main函數的函數體,這部分內容就是計算機要執行的內容。

4、在{  }裡面每一句話後面都有一個分號(;),在c語言中,我們把以一個分號結尾的一句話叫做一個c語言的語句,分號是語句結束的標志。

5、printf(「a=%d,b=%d,sum=%d\n」,a,b,sum); ----通過執行這條c語言系統提供給我們直接使用的屏幕輸出函數,用戶即可看到運行結果,本程序運行後,將在顯示器上顯示如下結果:

6、#include

7、程序中以 /*開頭並且以*/結尾的部分表示程序的注釋部分,注釋可以添加在程序的任何位置,為了提高程序的可讀性而添加,但計算機在執行主函數內容時完全忽略注釋部分,換而言之就是計算機當做注釋部分不存在於主函數中。

   •  2 C程序的生成過程

C程序是先由源文件經編譯生成目標文件,然後經過連接生成可執行文件,如圖所示。

                              編譯過程

 • 3 標識符

在編寫程序時,必須為函數、變數等命名,這個名字稱為標識符。C語言中標識符的命名規則如下:

標識符不能與程序中具有特殊意義的關鍵字相同,不能與用戶編制的函數名、C語言庫函數相同,在程序中各種標識符盡量不要重復,以便區分。選擇變數名和其他標識符時,應注意做到 「見名知義」。

標識符分為如下三類:

1、關鍵字

3、用戶標識符

用戶根據需要自己定義的標識符稱為用戶標識符。無論如何自定義標識符,都必須符合標識符的三條命名規則。

 • 4 常量

在程序運行中,其值不能被改變的量稱為常量。常量有5種類型:整型常量、實型常量、字元常量、字元串常量和符號常量。

(一)數值轉換

數字的四種表現形式:

在計算機內部,數字均以二進制形式表示和存放,用戶輸入的普通十進制數字都要被計算機轉換成二進制才能在計算機內部存儲,同樣計算機的運算結果也為二進制,一般要將其轉換成十進制數再輸出給用戶閱讀,這種轉換通常由計算機自動實現。

(1)將十進制轉換二進制、八進制和十六進制

除法:將十進制數除以2,記錄余數,得到的商繼續除以2,直到商為0,然後將各次相處所得的余數從後往前逆序排列,所得余數數字序列就是該十進制數對應的二進制數。八進制和十六進制轉換方法同上。

例:十進制數13轉換成二進制數的值為1101,轉換八進制為015,轉換成十六進制為D.

(2)將二進制、八進制和十六進制轉換成十進制

乘積求和:將二進制的每一位從低位到高位(右邊為低位,左邊為高位)分別乘以20,21,22。。。。,然後將這些積求和。

例如:(1101)2=(13)10     (317)8=(207)10     (23E)16=(574)10

(3)二進制與八進制、十六進制數之間的相互轉換

(二)整型常量

整型常量有3種形式:十進制整型常量、八進制整型常量和十六進制整型常量。

書寫方式如下:

(三)實型常量

實型常量有兩種表示形式:小數形式和指數形式。

(四)字元常量

(2)由一對單引號括起來,以反斜杠\開頭,後跟若干數字或者字母,比如『\n』,其中「\「是轉義的意思,後面跟不同的字元表示不同的意思,這類字元常量叫轉義字元。具體如圖所示 。

(五)字元串常量

C語言中,以雙引號括起來的,由若干個字元組成的序列即為字元串常量。

例:「ni hao」   「happy」等等。

(六)符號常量

例:計算圓的面積的c程序。

說明:

• 5 變數

變數就是其值可以改變的量。變數要有變數名,在內存中占據一定的存儲單元,存儲單元里存放的是該變數的值。不同類型的變數其存儲單元的大小不同,變數在使用前必須定義。

(一)整型變數

不同的編譯系統對上述四種整型數據所佔用的位數和數值范圍有不同的規定。

類型說明符

說明:

(二)實型變數

C語言中,實型變數分為單精度類型( float )和雙精度類型( double )兩種。如:

在vc中,float 型數據在內存中佔4個位元組(32位),double型數據佔8個位元組。單精度實數提供7位有效數字,雙精度實數提供15~16位有效數字。實型常量不分float型和double型,一個實型常量可以賦給一個float 型或double型變數,但變數根據其類型截取實型常量中相應的有效數字。

注意:實型變數只能存放實型值,不能用整型變數存放實型值,也不能用實型變數存放整型值。

(三)字元變數

字元變數用來存放字元常量,定義形式:

char  變數名;

其中關鍵字char定義字元型數據類型,佔用一個位元組的存儲單元。

將一個字元賦給一個字元變數時,並不是將該字元本身存儲到內存中,而是將該字元對應的ASCII碼存儲到內存單元中。例如,字元 ′A′ 的ASCII碼為65,在內存中的存放形式如下:01000001

由於在內存中字元以ASCII碼存放,它的存儲形式和整數的存儲形式類似,所以C語言中字元型數據與整型數據之間可以通用,一個字元能用字元的形式輸出,也能用整數的形式輸出,字元數據也能進行算術運算,此時相當於對它們的ASCII碼進行運算。

     •6 類型的自動轉換和強制轉換

當同一表達式中各數據的類型不同時,編譯程序會自動把它們轉變成同一類型後再進行計算。轉換優先順序為:

即左邊級別「低「的類型向右邊轉換。具體地說,若在表達式中優先順序最高的數據是double型,則此表達式中的其他數據均被轉換成double型,且計算結果也是double型;若在表達式中優先順序最高的數據是float型,則此表達式中的其他數據均被轉換成float型,且計算結果也是float型。

在做賦值運算時,若賦值號左右兩邊的類型不同,則賦值號右邊的類型向左邊的類型轉換;當右邊的類型高於左邊的類型時,則在轉換時對右邊的數據進行截取。

除自動轉換外,還有強制轉換,表示形式是:

討論:當a值賦值為3.4,b值賦值為2.7,(int)(a+b)和(int)a+b的值分別為多少?

   • 7  C運算符認識

C語言的運算符范圍很廣,可分為以下幾類:

1、算術運算符:用於各類數值運算。包括加(+)、減(-)、乘(*)、除(/)、求余(%)、自增(++)、自減(--)共七種。

2、賦值運算符:用於賦值運算,分為簡單賦值(=)、復合算術賦值(+=,-=,*=,/=,%=)和復合位運算賦值(&=,|=,^=,>>=,<<=)三類共十一種。

3、逗號運算符:用於把若干表達式組合成一個表達式(,)。

4、關系運算符:用於比較運算。包括大於(>)、小於(<)、等於(==)、 大於等於(>=)、小於等於(<=)和不等於(!=)六種。

5、邏輯運算符:用於邏輯運算。包括與(&&)、或(||)、非(!)三種。

6、條件運算符:這是一個三目運算符,用於條件求值(?:)。

7、位操作運算符:參與運算的量,按二進制位進行運算。包括位與(&)、位或(|)、位非(~)、位異或(^)、左移(<<)、右移(>>)六種。

8、指針運算符:用於取內容(*)和取地址(&)二種運算。

9.、求位元組數運算符:用於計算數據類型所佔的位元組數(sizeof)。

10、特殊運算符:有括弧(),下標[],成員(→,.)等幾種。

另外,按參與運算的對象個數,C語言運算符可分為:單目運算符 (如 !)、雙目運算符 (如+,- )和三目運算符 (如 ?  : )。

一、   基本的算術運算符

(1)+(加法運算符或正值運算符,如2+5)。

(2)-(減法運算符或負值運算符,如4-2)。

(3)*(乘法運算符,如3*8)。

(4)/(除法運算符,如11/5)。

/的運算分為兩種情況:

(5)%(模運算符或稱求余運算符,%兩側均應為整型數據,如9%7的值為2)。

需要說明的是:當運算對象為負數時,所得結果隨編譯器不同而不同,在vc中,結果的符號與被除數相同,比如:13%-2值為1,而-15%2值為-1.

二、   算術表達式和運算符的優先順序與結合性

算術表達式是用算術運算符和括弧將運算量(也稱操作數)連接起來的、符合C語言語法規則的表達式。運算對象包括函數、常量和變數等。

在計算機語言中,算術表達式的求值規律與數學中的四則運算的規律類似,其運算規則和要求如下。

(1)在算術表達式中,可使用多層圓括弧,但括弧必須配對。運算時從內層圓括弧開始,由內向外依次計算各表達式的值。

(2)在算術表達式中,對於不同優先順序的運算符,可按運算符的優先順序由高到低進行運算,若表達式中運算符的優先順序相同,則按運算符的結合方向進行運算。

(3)如果一個運算符兩側的操作數類型不同,則先利用自動轉換或強制類型轉換,使兩者具有相同類型,然後進行運算。

三、   自增自減運算符

作用:使變數的值增1或減1。

(1)只有變數才能用自增運算符 (++)和自減運算符(--),而常量或表達式不能用,如10++或(x+y)++都是不合法的。

(2)++和--的結合方向是「自右向左「,如 -i++ ,i的左邊是負號運算符,右邊是自增運算符,負號運算和自增運算都是 「自右向左「結合的,相當於 -(i++)。

在循環語句中常用到自增(減)運算符,在指針中也常用到該運算符,考生要弄清楚「i++」和「++i」及「i--」和「--i」的區別,特別弄清楚表達式的值和變數的值。

例:變數n的初始值為2,則

例:有以下程序

程序運行後的輸出結果是_____

A.12  35  13  35  14  36     B. 12  35  14  35  14  36

C.12  35  14  36  14  36     D. 12  35  14  35  14  35

解析:自增自減運算需要注意區分表達式的值和變數的值,表達式運算後,變數會自增自減運算,表達式和變數變化如下:

     •9 賦值運算符與賦值表達式

一、賦值運算符與賦值表達式

賦值符號 「=「就是賦值運算符,作用是將一個數據賦給一個變數或將一個變數的值賦給另一個變數,由賦值運算符組成的表達式稱為賦值表達式。一般形式為:

變數名 = 表達式

在程序中可以多次給一個變數賦值,每賦一次值,與它相應的存儲單元中的數據就被更新一次,內存中當前的數據就是最後一次所賦值的那個數據。

說明:

a、如果賦值號兩邊的運算對象類型不一致,系統會自動進行類型轉換,轉換的規則:將賦值號右邊表達式的值的類型轉換成賦值號左邊變數的類型,

b、 可以將復製表達式的值再賦值給變數,形成連續賦值。

二、復合的賦值運算符

在賦值運算符之前加上其他運算符可以構成復合賦值運算符。其中與算術運算有關的復合運算符是:+=,-=,*=,/=,%= 。

兩個符號之間不可以有空格,復合賦值運算符的優先順序與賦值運算符的相同。表達式n+=1等價於n=n+1,作用是取變數n中的值增1再賦給變數n,其他復合的賦值運算符的運算規則依次類推。

如求表達a+=a-=a*a 的值,其中a的初值為12 。

步驟:

   •10  逗號運算符和逗號表達式

在c語言中,逗號除了作為分隔符,還可以用作一種運算符----逗號運算符,用逗號運算符將幾個表達式連接起來,例如a=b+c,a=b*c等稱為逗號表達式。

一般形式為:

表達式1 ,表達式2 ,表達式3 , …,表達式n

例:x=2,y=3,z=4

逗號表達式具有從左至右的結合性,即先求解表達式1,然後依次求解表達式2,直到表達式n的值。表達式n的值就是整個逗號表達式的值。上述的逗號表達式的值就是表達式z=4的值4.需要注意的是,逗號運算符是所有運算符中級別最低的。

例:有如下程序段:

程序顯示結果為:y=6,x=6

討論:將y=(x=a+b),(b+c);改為y=((x=a+b),b+c) 的程序結果?

  • 11 關系運算符和關系表達式

一、   C語言中的邏輯值

C語言中的邏輯值只有兩個:真(true)和假(flase)。用非零代表真,用零代表假。因此,對於任意一個表達式,如果它的值為零,就代表一個假值,如果它的值為非零,就代表一個真值。只要值不是零,不管是正數,負數,整數,實數,都代表一個真值。例如-5的邏輯值為真。

二、   關系運算符及其優先次序

C語言提供了6種關系運算符,見表

由兩個字元組成的運算符之間不可以加空格,關系運算符都是雙目運算符。

(1)結合性:自左向右。

(2)優先次序:前4種關系運算符( <,<=,>=,> )的優先順序別相同,後兩種 (==,!=)優先順序相同,且前4種優先順序高於後兩種;關系運算符的優先順序低於算術運算符,高於賦值運算符。

三、   關系表達式

由關系運算符連接而成的表達式稱為關系表達式。

例如:a>b,(a=7)>(b=10)等都是合法的關系表達式。

關系表達式的結果有兩個:0和1,。其中0表示假,1表示真。如果關系表達式成立,則值為真,如果關系表達式不成立,則值為假。

例:變數a的值為5,b的值為6,那麼關系表達式a>b的值為假,即為0.而關系表達式

(a=13)>(b=10)的值為真,即為1。

當關系運算符兩邊值的類型不一致時,若一邊是整型,一邊是實型,系統將自動把整型數轉化為實型數,然後再進行比較。

    •12 邏輯運算符和邏輯表達式

一、   邏輯運算符及其優先順序

C語言提供了3種邏輯運算符,如下表。

二、   邏輯表達式

「&&」和「||」的運算對象有兩個,故它們都是雙目運算符,而!的運算對象只有一個,因此它是單目運算符。邏輯運算舉例如下:

(1)a&&b: 當&&兩邊都為「真」時,表達式a&&b的值才是真。

值得注意的是:在數學中,關系式0

(2)a||b: 當||兩邊有一個為「真」時,表達式a||b的值就是真。

(3)!a:   表示取反,如果a為真,則!A為假,反之亦然。例如!-5的值就為0.

在C語言中,由&&或||組成的邏輯表達式,在某些特定情況下會產生「短路「現象。

(1)x && y && z ,只有當x為真(非0)時,才需要判別y的值;只有x和y都為真時,才需要去判別z的值;只要x為假就不必判別y和z,整個表達式的值為0。口訣:「一假必假」。

例:(!5==1)&&(++i==0)  (!5==1)表達式的值為0,所以計算機運行中就跳過(++i==0)此表達式,(!5==1)&&(++i==0)表達式的值為0.

(2)x||y||z ,只要x的值為真(非零),就不必判別y和z的值,整個表達式的值為1,只有x的值為假,才需要判別y的值,只有x和y的值同時為假才需要判別z的值,口訣:「一真必真」。

   •13 位運算

一、   位運算符

在計算機中,數據都是以二進制數形式存放的,位運算就是指對存儲單元中二進制位的運算。C語言提供6種位運算符。

二、位運算

位運算符 &  |~<<  >>  ∧ 按優先順序從高到低排列的順序是:

位運算符中求反運算「~「優先順序最高,而左移和右移相同,居於第二,接下來的順序是按位與 「&「、按位異或 「∧「和按位或 「|「。順序為~  <<  >>  &  ∧  |  。

例1左移運算符「<<」是雙目運算符。其功能把「<< 」左邊的運算數的各二進位全部左移若干位,由「<<」右邊的數指定移動的位數,高位丟棄,低位補0。

例 2右移運算符「>>」是雙目運算符。其功能是把「>> 」左邊的運算數的各二進位全部右移若干位,「>>」右邊的數指定移動的位數。

應該說明的是,對於有符號數,在右移時,符號位將隨同移動。當為正數時,最高位補0,而為負數時,符號位為1,最高位是補0或是補1 取決於編譯系統的規定。

例 3 設二進制數a是00101101 ,若通過異或運算a∧b 使a的高4位取反,低4位不變,則二進制數b是。

解析:異或運算常用來使特定位翻轉,只要使需翻轉的位與1進行異或操作就可以了,因為原數中值為1的位與1進行異或運算得0 ,原數中值為0的位與1進行異或運算結果得1。而與0進行異或的位將保持原值。異或運算還可用來交換兩個值,不用臨時變數。

所以本題的答案為: 11110000 。

㈣ C語言中能進行數學運算的運算符包括哪些

C語言中能進行數學運算的運算符包括三類:
一、常規的數學運算,包括加(+),減(-),乘(*),除(/),和模除(%)。
形式為
a op b
結果為對應的數學運算結果。
其中模除%又稱作取余,計算a除以b得到的余數,是唯一一個只能用來做整型計算的數學運算符。
二、自加(++)自減(--)運算:
自加和自減屬於單目運算,使用後使變數自加1或者自減1.有前置自加自減和後置自加自減區別。形式為
++a, a++, --a, a--,
四種。
三、帶賦值的運算,即在一中提到的物種運算符加上=,組合成復合運算符+=, -=, *=, /=和%=.
對於這類運算符,形式為
a op b
表示a=a op的前一個符號 b。
比如
a+=b
等效於
a=a+b
這是一類特殊的數學運算操作符。

㈤ 在C語言中復合賦值運算符有什麼樣的作用

在賦值運算符當中,還有一類C/C++獨有的復合賦值運算符。它們實際上是一種縮寫形式,使得對變數的改變更為簡潔。
Total=Total+3;
乍一看這行代碼,似乎有問題,這是不可能成立的。其實還是老樣子,'='是賦值不是等於。它的意思是本身的值加3,然後在賦值給本身。為了簡化,上面的代碼也可以寫成:
Total+=3;
復合賦值運算符有下列這些:符號 功能
+=加法賦值 =減法賦值 *=乘法賦值 /=除法賦值 %=模運算賦值 左移賦值 ルAA
右移賦值 &=
位邏輯與賦值 位邏輯或賦值 =1
=位邏輯異或賦值
上面的十個復合賦值運算符中,後面五個我們到以後位運算時再說明。那麼看了上面的復合賦值運算符,有人就會問,到底Total=Total+3;與Tota
tal+=3;
有沒有區別? 答案是有的,對於A=
A=A+1
+1,表達式A被計算了兩次,對於復合運算符
A+=1
,表達式A僅計 算了一次。一般的來說,這種區別對於程序的運行沒有多大影響,但是當表達式作為函數的返回值時,函數就被調用了兩次(以後再說明),而且如果使用普通的賦值運算符,也會加大程序的開銷,使效率降低。

㈥ 高手們幫我看看c語言程序,請給每行代碼和功能注釋

在初學C語言時,可能會遇到有些問題理解不透,或者表達方式與以往數學學習中不同(如運算符等),這就要求不氣餒,不明白的地方多問多想,鼓足勇氣進行學習,待學完後面的章節知識,前面的問題也就迎刃而解了,這一方面我感覺是我們同學最欠缺,大多學不好的就是因為一開始遇到困難就放棄,曾經和好多同學談他的問題,回答是聽不懂、不想聽、放棄這樣三個過程,我反問,這節課你聽過課嗎?回答又是沒有,根本就沒聽過課,怎麼說自己聽不懂呢?相應的根本就沒學習,又談何學的好?
學習C語言始終要記住「曙光在前頭」和「千金難買回頭看」,「千金難買回頭看」是學習知識的重要方法,就是說,學習後面的知識,不要忘了回頭弄清遺留下的問題和加深理解前面的知識,這是我們學生最不易做到的,然而卻又是最重要的。學習C語言就是要經過幾個反復,才能前後貫穿,積累應該掌握的C知識。
那麼,我們如何學好《C程序設計》呢?
一.學好C語言的運算符和運算順序
這是學好《C程序設計》的基礎,C語言的運算非常靈活,功能十分豐富,運算種類遠多於其它程序設計語言。在表達式方面較其它程序語言更為簡潔,如自加、自減、逗號運算和三目運算使表達式更為簡單,但初學者往往會覺的這種表達式難讀,關鍵原因就是對運算符和運算順序理解不透不全。當多種不同運算組成一個運算表達式,即一個運算式中出現多種運算符時,運算的優先順序和結合規則顯得十分重要。在學習中,只要我們對此合理進行分類,找出它們與我們在數學中所學到運算之間的不同點之後,記住這些運算也就不困難了,有些運算符在理解後更會牢記心中,將來用起來得心應手,而有些可暫時放棄不記,等用到時再記不遲。
先要明確運算符按優先順序不同分類,《C程序設計》運算符可分為15種優先順序,從高到低,優先順序為1 ~ 15,除第2、13級和第14級為從右至左結合外,其它都是從左至右結合,它決定同級運算符的運算順序.
二.學好C語言的四種程序結構
(1)順序結構
順序結構的程序設計是最簡單的,只要按照解決問題的順序寫出相應的語句就行,它的執行順序是自上而下,依次執行。
例如;a = 3,b = 5,現交換a,b的值,這個問題就好像交換兩個杯子水,這當然要用到第三個杯子,假如第三個杯子是c,那麼正確的程序為: c = a; a = b; b = c; 執行結果是a = 5,b = c = 3如果改變其順序,寫成:a = b; c = a; b = c; 則執行結果就變成a = b = c = 5,不能達到預期的目的,初學者最容易犯這種錯誤。 順序結構可以獨立使用構成一個簡單的完整程序,常見的輸入、計算,輸出三步曲的程序就是順序結構,例如計算圓的面積,其程序的語句順序就是輸入圓的半徑r,計算s = 3.14159*r*r,輸出圓的面積s。不過大多數情況下順序結構都是作為程序的一部分,與其它結構一起構成一個復雜的程序,例如分支結構中的復合語句、循環結構中的循環體等。
(2) 分支結構
順序結構的程序雖然能解決計算、輸出等問題,但不能做判斷再選擇。對於要先做判斷再選擇的問題就要使用分支結構。分支結構的執行是依據一定的條件選擇執行路徑,而不是嚴格按照語句出現的物理順序。分支結構的程序設計方法的關鍵在於構造合適的分支條件和分析程序流程,根據不同的程序流程選擇適當的分支語句。分支結構適合於帶有邏輯或關系比較等條件判斷的計算,設計這類程序時往往都要先繪制其程序流程圖,然後根據程序流程寫出源程序,這樣做把程序設計分析與語言分開,使得問題簡單化,易於理解。程序流程圖是根據解題分析所繪制的程序執行流程圖。
學習分支結構不要被分支嵌套所迷惑,只要正確繪制出流程圖,弄清各分支所要執行的功能,嵌套結構也就不難了。嵌套只不過是分支中又包括分支語句而已,不是新知識,只要對雙分支的理解清楚,分支嵌套是不難的。下面我介紹幾種基本的分支結構。
①if(條件)
{分支體}
這種分支結構中的分支體可以是一條語句,此時「{ }」可以省略,也可以是多條語句即復合語句。它有兩條分支路徑可選,一是當條件為真,執行分支體,否則跳過分支體,這時分支體就不會執行。如:要計算x的絕對值,根據絕對值定義,我們知道,當x>=0時,其絕對值不變,而x<0時其絕對值是為x的反號,因此程序段為:if(x<0) x=-x;
②if(條件)
{分支1}
else
{分支2}
這是典型的分支結構,如果條件成立,執行分支1,否則執行分支2,分支1和分支2都可以是1條或若干條語句構成。如:求ax^2+bx+c=0的根
分析:因為當b^2-4ac>=0時,方程有兩個實根,否則(b^2-4ac<0)有兩個共軛復根。其程序段如下:
d=b*b-4*a*c;
if(d>=0)
{x1=(-b+sqrt(d))/2a;
x2=(-b-sqrt(d))/2a;
printf(「x1=%8.4f,x2=%8.4f\n」,x1,x2);
}
else
{r=-b/(2*a);
i =sqrt(-d)/(2*a);
printf(「x1=%8.4f+%8.4fi\n」r, i);
printf(「x2=%8.4f-%8.4fi\n」r,i)
}
③嵌套分支語句:其語句格式為:
if(條件1) {分支1};
else if(條件2) {分支2}
else if(條件3) {分支3}
……
else if(條件n) {分支n}
else {分支n+1}
嵌套分支語句雖可解決多個入口和出口的問題,但超過3重嵌套後,語句結構變得非常復雜,對於程序的閱讀和理解都極為不便,建議嵌套在3重以內,超過3重可以用下面的語句。
④switch開關語句:該語句也是多分支選擇語句,到底執行哪一塊,取決於開關設置,也就是表達式的值與常量表達式相匹配的那一路,它不同if…else 語句,它的所有分支都是並列的,程序執行時,由第一分支開始查找,如果相匹配,執行其後的塊,接著執行第2分支,第3分支……的塊,直到遇到break語句;如果不匹配,查找下一個分支是否匹配。這個語句在應用時要特別注意開關條件的合理設置以及break語句的合理應用。
(3)循環結構:
循環結構可以減少源程序重復書寫的工作量,用來描述重復執行某段演算法的問題,這是程序設計中最能發揮計算機特長的程序結構,C語言中提供四種循環,即goto循環、while循環、do ?Cwhile循環和for循環。四種循環可以用來處理同一問題,一般情況下它們可以互相代替換,但一般不提倡用goto循環,因為強制改變程序的順序經常會給程序的運行帶來不可預料的錯誤,在學習中我們主要學習while、do…while、for三種循環。常用的三種循環結構學習的重點在於弄清它們相同與不同之處,以便在不同場合下使用,這就要清楚三種循環的格式和執行順序,將每種循環的流程圖理解透徹後就會明白如何替換使用,如把while循環的例題,用for語句重新編寫一個程序,這樣能更好地理解它們的作用。特別要注意在循環體內應包含趨於結束的語句(即循環變數值的改變),否則就可能成了一個死循環,這是初學者的一個常見錯誤。
在學完這三個循環後,應明確它們的異同點:用while和do…while循環時,循環變數的初始化的操作應在循環體之前,而for循環一般在語句1中進行的;while 循環和for循環都是先判斷表達式,後執行循環體,而do…while循環是先執行循環體後判斷表達式,也就是說do…while的循環體最少被執行一次,而while 循環和for就可能一次都不執行。另外還要注意的是這三種循環都可以用break語句跳出循環,用continue語句結束本次循環,而goto語句與if構成的循環,是不能用break和 continue語句進行控制的。
順序結構、分支結構和循環結構並不彼此孤立的,在循環中可以有分支、順序結構,分支中也可以有循環、順序結構,其實不管哪種結構,我們均可廣義的把它們看成一個語句。在實際編程過程中常將這三種結構相互結合以實現各種演算法,設計出相應程序,但是要編程的問題較大,編寫出的程序就往往很長、結構重復多,造成可讀性差,難以理解,解決這個問題的方法是將C程序設計成模塊化結構。
(4)模塊化程序結構
C語言的模塊化程序結構用函數來實現,即將復雜的C程序分為若干模塊,每個模塊都編寫成一個C函數,然後通過主函數調用函數及函數調用函數來實現一大型問題的C程序編寫,因此常說:C程序=主函數+子函數。 因此,對函數的定義、調用、值的返回等中要尤其注重理解和應用,並通過上機調試加以鞏固。
三.掌握一些簡單的演算法
編程其實一大部分工作就是分析問題,找到解決問題的方法,再以相應的編程語言寫出代碼。這就要求掌握演算法,根據我們的《C程序設計》教學大綱中,只要求我們掌握一些簡單的演算法,在掌握這些基本演算法後,要完成對問題的分析就容易了。如兩個數的交換、三個數的比較、選擇法排序和冒泡法排序,這就要求我們要清楚這些演算法的內在含義
結語:當我們把握好上述幾方面後,只要同學們能克服畏難、厭學、上課能專心聽講,做好練習與上機調試,其實C語言並不難學
C源程序的關鍵字---------------------------------------------------------------------------------------
所謂關鍵字就是已被C語言本身使用, 不能作其它用途使用的字。例如關鍵字不能用作變數名、函數名等
由ANSI標準定義的C語言關鍵字共32個 :
auto double int struct break else long switch
case enum register typedef char extern return union
const float short unsigned continue for signed void
default goto sizeof volatile do if while static
根據關鍵字的作用,可以將關鍵字分為數據類型關鍵字和流程式控制制關鍵字兩大類。
1 數據類型關鍵字
A基本數據類型(5個)
void :聲明函數無返回值或無參數,聲明無類型指針,顯式丟棄運算結果
char :字元型類型數據,屬於整型數據的一種
int :整型數據,通常為編譯器指定的機器字長
float :單精度浮點型數據,屬於浮點數據的一種
double :雙精度浮點型數據,屬於浮點數據的一種
B 類型修飾關鍵字(4個)
short :修飾int,短整型數據,可省略被修飾的int。
long :修飾int,長整形數據,可省略被修飾的int。
signed :修飾整型數據,有符號數據類型
unsigned :修飾整型數據,無符號數據類型
C 復雜類型關鍵字(5個)
struct :結構體聲明
union :共用體聲明
enum :枚舉聲明
typedef :聲明類型別名
sizeof :得到特定類型或特定類型變數的大小
D 存儲級別關鍵字(6個)
auto :指定為自動變數,由編譯器自動分配及釋放。通常在棧上分配
static :指定為靜態變數,分配在靜態變數區,修飾函數時,指定函數作用域為文件內部
register :指定為寄存器變數,建議編譯器將變數存儲到寄存器中使用,也可以修飾函數形參,建議編譯器通過寄存器而不是堆棧傳遞參數
extern :指定對應變數為外部變數,即標示變數或者函數的定義在別的文件中,提示編譯器遇到此變數和函數時在其他模塊中尋找其定義。
const :與volatile合稱「cv特性」,指定變數不可被當前線程/進程改變(但有可能被系統或其他線程/進程改變)
volatile :與const合稱「cv特性」,指定變數的值有可能會被系統或其他進程/線程改變,強制編譯器每次從內存中取得該變數的值
2 流程式控制制關鍵字
A 跳轉結構(4個)
return :用在函數體中,返回特定值(或者是void值,即不返回值)
continue :結束當前循環,開始下一輪循環
break :跳出當前循環或switch結構
goto :無條件跳轉語句
B 分支結構(5個)
if :條件語句
else :條件語句否定分支(與if連用)
switch :開關語句(多重分支語句)
case :開關語句中的分支標記
default :開關語句中的「其他」分治,可選。
C 循環結構(3個)
for :for循環結構,for(1;2;3)4;的執行順序為1->2->4->3->2...循環,其中2為循環條件
do :do循環結構,do 1 while(2); 的執行順序是 1->2->1...循環,2為循環條件
while :while循環結構,while(1) 2; 的執行順序是1->2->1...循環,1為循環條件
以上循環語句,當循環條件表達式為真則繼續循環,為假則跳出循環。
[編輯本段]新標准
在ANSI標准化後,C語言的標准在一段相當的時間內都保持不變,盡管C++繼續在改進。(實際上,Normative Amendment1在1995年已經開發了一個新的C語言版本。但是這個版本很少為人所知。)標准在90年代才經歷了改進,這就是ISO9899:1999(1999年出版)。這個版本就是通常提及的C99。它被ANSI於2000年三月採用。
在C99中包括的特性有:
對編譯器限制增加了,比如源程序每行要求至少支持到 4095 位元組,變數名函數名的要求支持到 63 位元組 (extern 要求支持到 31)
預處理增強了。例如:
宏支持取參數 #define Macro(...) __VA_ARGS__
使用宏的時候,參數如果不寫,宏里用 #,## 這樣的東西會擴展成空串。(以前會出錯的)
支持 // 行注釋(這個特性實際上在C89的很多編譯器上已經被支持了)
增加了新關鍵字 restrict, inline, _Complex, _Imaginary, _Bool
支持 long long, long double _Complex, float _Complex 這樣的類型
支持 <: :> <% %> %: %:%: ,等等奇怪的符號替代
支持了不定長的數組。數組的長度就可以用變數了。聲明類型的時候呢,就用 int a[*] 這樣的寫法。不過考慮到效率和實現,這玩意並不是一個新類型。所以就不能用在全局裡,或者 struct union 裡面,如果你用了這樣的東西,goto 語句就受限制了。
變數聲明不必放在語句塊的開頭,for 語句提倡這么寫 for(int i=0;i<100;++i) 就是說,int i 的聲明放在裡面,i 只在 for 裡面有效。(VC沒有遵守這條標准,i 在 for 外也有效)
當一個類似結構的東西需要臨時構造的時候,可以用 (type_name){xx,xx,xx} 這有點像 C++ 的構造函數
初始化結構的時候現在可以這樣寫:
struct {int a[3], b;} hehe[] = { [0].a = , [1].a = 2 };
struct {int a, b, c, d;} hehe = { .a = 1, .c = 3, 4, .b = 5} // 3,4 是對 .c,.d 賦值的
字元串裡面,\u 支持 unicode 的字元
支持 16 進制的浮點數的描述
所以 printf scanf 的格式化串多支持了 ll / LL (VC6 里用的 I64) 對應新的 long long 類型。
浮點數的內部數據描述支持了新標准,這個可以用 #pragma 編譯器指定
除了已經有的 __line__ __file__ 以外,又支持了一個 __func__ 可以得到當前的函數名
對於非常數的表達式,也允許編譯器做化簡
修改了對於 / % 處理負數上的定義,比如老的標准里 -22 / 7 = -3, -22 % 7 = -1 而現在 -22 / 7 = -4, -22 % 7 = 6
取消了不寫函數返回類型默認就是 int 的規定
允許 struct 定義的最後一個數組寫做 [] 不指定其長度描述
const const int i; 將被當作 const int i; 處理
增加和修改了一些標准頭文件, 比如定義 bool 的 <stdbool.h> 定義一些標准長度的 int 的 <inttypes.h> 定義復數的 <complex.h> 定義寬字元的 <wctype.h> 有點泛型味道的數學函數 <tgmath.h> 跟浮點數有關的 <fenv.h>。<stdarg.h> 里多了一個 va_ 可以復制 ... 的參數。<time.h> 里多了個 struct tmx 對 struct tm 做了擴展
輸入輸出對寬字元還有長整數等做了相應的支持
相對於c89的變化還有
1、增加restrict指針
C99中增加了公適用於指針的restrict類型修飾符,它是初始訪問指針所指對象的惟一途徑,因此只有藉助restrict指針表達式才能訪問對象。restrict指針指針主要用做函數變元,或者指向由malloc()函數所分配的內存變數。restrict數據類型不改變程序的語義。
如果某個函數定義了兩個restrict指針變元,編譯程序就假定它們指向兩個不同的對象,memcpy()函數就是restrict指針的一個典型應用示例。C89中memcpy()函數原型如下:
代碼: void *memcpy (void *s1, const void *s2, size_t size);
如果s1和s2所指向的對象重疊,其操作就是未定義的。memcpy()函數只能用於不重疊的對象。C99中memcpy()函數原型如下:代碼: void *memcpy(void *restrict s1, const void *restrict s2,size_t size);
通過使用restrict修飾s1和s2 變元,可確保它們在該原型中指向不同的對象。
2、inline(內聯)關鍵字
內聯函數除了保持結構化和函數式的定義方式外,還能使程序員寫出高效率的代碼.函數的每次調用與返回都會消耗相當大的系統資源,尤其是當函數調用發生在重復次數很多的循環語句中時.一般情況下,當發生一次函數調用時,變元需要進棧,各種寄存器內存需要保存.當函數返回時,寄存器的內容需要恢復。如果該函數在代碼內進行聯機擴展,當代碼執行時,這些保存和恢復操作旅遊活動會再發生,而且函數調用的執行速度也會大大加快。函數的聯機擴展會產生較長的代碼,所以只應該內聯對應用程序性能有顯著影響的函數以及長度較短的函數
3、新增數據類型
_Bool
值是0或1。C99中增加了用來定義bool、true以及false宏的頭文件夾<stdbool.h>,以便程序員能夠編寫同時兼容於C與C++的應用程序。在編寫新的應用程序時,應該使用
<stdbool.h>頭文件中的bool宏。
_Complex and _Imaginary
C99標准中定義的復數類型如下:float_Complex; float_Imaginary; double_Complex; double_Imaginary; long double_Complex; long double_Imaginary.
<complex.h>頭文件中定義了complex和imaginary宏,並將它們擴展為_Complex和_Imaginary,因此在編寫新的應用程序時,應該使用<stdbool.h>頭文件中的complex和imaginary宏。
long long int
C99標准中引進了long long int(-(2e63 - 1)至2e63 - 1)和unsigned long long int(0 - 2e64 - 1)。long long int能夠支持的整數長度為64位。
4、對數組的增強
可變長數組
C99中,程序員聲明數組時,數組的維數可以由任一有效的整型表達式確定,包括只在運行時才能確定其值的表達式,這類數組就叫做可變長數組,但是只有局部數組才可以是變長的.
可變長數組的維數在數組生存期內是不變的,也就是說,可變長數組不是動態的.可以變化的只是數組的大小.可以使用*來定義不確定長的可變長數組。

㈦ C語言if語句 復合語句什麼意思

if 中的復合語句,意思是 當if成立時,你要執行多個語句時,要把這些語句用{}括起來,這些被{ } 括起來的語句就叫復合語句,在語法上,復合語句被認為是一句.你可以理解為用小零件合成了一個大的東西

㈧ 復合賦值運算符講解

位運算符
學過匯編的朋友都知道匯編對位的處理能力是很強的,但是C語言也能對運算對象進行按位操作,從而使C語言也能具有一定的對硬體直接進行操作的能力。位運算符的作用是按位對變數進行運算,但是並不改變參與運算的變數的值。如果要求按位改變變數的值,則要利用相應的賦值運算。還有就是位運算符是不能用來對浮點型數據進行操作的。C51中共有6種位運算符。
位運算一般的表達形式如下:
變數1 位運算符 變數2
位運算符也有優先順序,從高到低依次是:"~"(按位取反)→"<<"(左移) →">>"(右移) →"&"(按位與)→"^"(按位異或)→"|"(按位或)
表7-1是位邏輯運算符的真值表,X表示變數1,Y表示變數2

X Y ~X ~Y X&Y X|Y X^Y
0 0 1 1 0 0 0
0 1 1 0 0 1 1
1 0 0 1 0 1 1
1 1 0 0 1 1 0

表7-1 按位取反,與,或和異或的邏輯真值表

利用以前建立起來的實驗板,我們來做個實驗驗證一下位運算是否真是不改變參與變數的值,同時學習位運算的表達形式。程序很簡單,用P1口做運算變數,P1.0-P1.7對應P1變數的最低位到最高位,通過連接在P1口上的LED我們便可以直觀看到每個位運算後變數是否有改變或如何改變。程序如下:
#include <at89x51.h>
void main(void)
{
unsigned int a;
unsigned int b;
unsigned char temp; //臨時變數
P1 = 0xAA; //點亮D1,D3,D5,D7 P1口的二進制為10101010,為0時點亮LED
for (a=0;a<1000;a++)
for (b=0;b<1000;b++); //延時
temp = P1 & 0x7; //單純的寫P1|0x7是沒有意義的,因為沒有變數被影響,不會被編譯
//執行P1|0x7後結果存入temp,這時改變的是temp,但P1不會被影響。
//這時LED沒有變化,仍然是D1,D3,D5,D7亮
for (a=0;a<1000;a++)
for (b=0;b<1000;b++); //延時
P1 = 0xFF; //熄滅LED
for (a=0;a<1000;a++)
for (b=0;b<1000;b++); //延時
P1 = 0xAA; //點亮D1,D3,D5,D7 P1口的二進制為10101010,為0時點亮LED
for (a=0;a<1000;a++)
for (b=0;b<1000;b++); //延時
P1 = P1 & 0x7; //這時LED會變得只有D2滅
//因為之前P1=0xAA=10101010
//與0x7位與 0x7=00000111
//結果存入P1 P1=00000010 //位為O時點亮LED,電路看第三課
for (a=0;a<1000;a++)
for (b=0;b<1000;b++); //延時
P1 = 0xFF; //熄滅LED
while(1);
//大家可以根據上面的程序去做位或,左移,取反等等。
}

復合賦值運算符
復合賦值運算符就是在賦值運算符"="的前面加上其他運算符。以下是C語言中的復合賦值運算符:
+= 加法賦值 >>= 右移位賦值
-= 減法賦值 &= 邏輯與賦值
*= 乘法賦值 |= 邏輯或賦值
/= 除法賦值 ^= 邏輯異或賦值
%= 取模賦值 -= 邏輯非賦值
<<= 左移位賦值

復合運算的一般形式為:
變數 復合賦值運算符 表達式

其含義就是變數與表達式先進行運算符所要求的運算,再把運算結果賦值給參與運算的變數。其實這是C語言中一種簡化程序的一種方法,凡是二目運算都可以用復合賦值運算符去簡化表達。例如:
a+=56等價於a=a+56
y/=x+9 等價於 y=y/(x+9)
很明顯採用復合賦值運算符會降低程序的可讀性,但這樣卻可以使程序代碼簡單化,並能提高編譯的效率。對於初學C語言的朋友在編程時最好還是根據自己的理解力和習慣去使用程序表達的方式,不要一味追求程序代碼的短小。

逗號運算符
如果你有編程的經驗,那麼對逗號的作用也不會陌生了。如在VB中"Dim a,b,c"的逗號就是把多個變數定義為同一類型的變數,在C也一樣,如"int a,b,c",這些例子說明逗號用於分隔表達式用。但在C語言中逗號還是一種特殊的運算符,也就是逗號運算符,可以用它將兩個或多個表達式連接起來,形成逗號表達式。逗號表達式的一般形式為:
表達式1,表達式2,表達式3……表達式n
這樣用逗號運算符組成的表達式在程序運行時,是從左到右計算出各個表達式的值,而整個用逗號運算符組成的表達式的值等於最右邊表達式的值,就是"表達式n"的值。在實際的應用中,大部分情況下,使用逗號表達式的目的只是為了分別得到名個表達式的值,而並不一定要得到和使用整個逗號表達式的值。要注意的還有,並不是在程序的任何位置出現的逗號,都可以認為是逗號運算符。如函數中的參數,同類型變數的定義中的逗號只是用來間隔之用而不是逗號運算符。

條件運算符
上面我們說過C語言中有一個三目運算符,它就是"?:"條件運算符,它要求有三個運算對象。它可以把三個表達式連接構成一個條件表達式。條件表達式的一般形式如下:
邏輯表達式? 表達式1 : 表達式2
條件運算符的作用簡單來說就是根據邏輯表達式的值選擇使用表達式的值。當邏輯表達式的值為真時(非0值)時,整個表達式的值為表達式1的值;當邏輯表達式的值為假(值為0)時,整個表達式的值為表達式2的值。要注意的是條件表達式中邏輯表達式的類型可以與表達式1和表達式2的類型不一樣。下面是一個邏輯表達式的例子。

如有a=1,b=2這時我們要求是取ab兩數中的較小的值放入min變數中,也許你會這樣寫:
if (a<b)
min = a;
else
min = b; //這一段的意思是當a<b時min的值為a的值,否則為b的值。

用條件運算符去構成條件表達式就變得簡單明了了:
min = (a<b)?a : b
很明顯它的結果和含意都和上面的一段程序是一樣的,但是代碼卻比上一段程序少很多,編譯的效率也相對要高,但有著和復合賦值表達式一樣的缺點就是可讀性相對效差。在實際應用時根據自己要習慣使用,就我自己來說我喜歡使用較為好讀的方式和加上適當的註解,這樣可以有助於程序的調試和編寫,也便於日後的修改讀寫。

指針和地址運算符
在第四課我們學習數據類型時,學習過指針類型,知道它是一種存放指向另一個數據的地址的變數類型。指針是C語言中一個十分重要的概念,也是學習C語言中的一個難點。對於指針將會在第九課中做詳細的講解。在這里我們先來了解一下C語言中提供的兩個專門用於指針和地址的運算符:
* 取內容
& 取地址
取內容和地址的一般形式分別為:
變數 = * 指針變數
指針變數 = & 目標變數

取內容運算是將指針變數所指向的目標變數的值賦給左邊的變數;取地址運算是將目標變數的地址賦給左邊的變數。要注意的是:指針變數中只能存放地址(也就是指針型數據),一般情況下不要將非指針類型的數據賦值給一個指針變數。
下面來看一個例子,並用一個圖表和實例去簡單理解指針的用法和含義。

設有兩個unsigned int 變數 ABC處CBA 存放在0x0028,0x002A中

另有一個指針變數 portA 存放在0x002C中

那麼我們寫這樣一段程序去看看*,&的運算結果

unsigned int data ABC _at_ 0x0028;

unsigned int data CBA _at_ 0x002A;

unsigned int data *Port _at_ 0x002C;

#include <at89x51.h>

#include <stdio.h>

void main(void)

{

SCON = 0x50; //串口方式1,允許接收

TMOD = 0x20; //定時器1定時方式2

TH1 = 0xE8; //11.0592MHz 1200波特率

TL1 = 0xE8;

TI = 1;

TR1 = 1; //啟動定時器

ABC = 10; //設初值

CBA = 20;

Port = &CBA; //取CBA的地址放到指針變數Port

*Port = 100; //更改指針變數Port所指向的地址的內容

printf("1: CBA=%d\n",CBA); //顯示此時CBA的值

Port = &ABC; //取ABC的地址放到指針變數Port

CBA = *Port; //把當前Port所指的地址的內容賦給變數CBA

printf("2: CBA=%d\n",CBA); //顯示此時CBA的值

printf(" ABC=%d\n",ABC); //顯示ABC的值

}

程序初始時


地址
說明

0x00
0x002DH

0x00
0x002CH

0x00
0x002BH

0x00
0x002AH

0x0A
0x0029H

0x00
0x0028H

執行ABC = 10;向ABC所指的地址0x28H寫入10(0xA),因ABC是int類型要佔用0x28H和0x29H兩個位元組的內存空間,低位位元組會放入高地址中,所以0x28H中放入0x00,0x29H中放入0x0A


地址
說明

0x00
0x002DH

0x00
0x002CH

0x00
0x002BH

0x00
0x002AH

0x0A
0x0029H
ABC為int類型佔用兩位元組

0x00
0x0028H

執行CBA = 20;原理和上一句一樣


地址
說明

0x00
0x002DH

0x00
0x002CH

0x14
0x002BH
CBA為int類型佔用兩位元組

0x00
0x002AH

0x0A
0x0029H
ABC為int類型佔用兩位元組

0x00
0x0028H

執行Port = &CBA; 取CBA的首地址放到指針變數Port


地址
說明

0x00
0x002DH

0x2A
0x002CH
CBA的首地址存入Port

0x14
0x002BH

0x00
0x002AH

0x0A
0x0029H

0x00
0x0028H

*Port = 100; 更改指針變數Port所指向的地址的內容


地址
說明

0x00
0x002DH

0x2A
0x002CH

0x64
0x002BH
Port指向了CBA所在地址2AH

0x00
0x002AH
並存入100

0x0A
0x0029H

0x00
0x0028H

其它的語句也是一樣的道理,大家可以用Keil的單步執行和打開存儲器查看器一看,這樣就更容易理解了。

圖7-6 存儲器查看窗

圖7-7 在串列調試窗口的最終結果

sizeof運算符
看上去這確實是個奇怪的運算符,有點像函數,卻又不是。大家看到size應該就猜到是和大小有關的吧?是的,sizeof是用來求數據類型、變數或是表達式的位元組數的一個運算符,但它並不像"="之類運算符那樣在程序執行後才能計算出結果,它是直接在編譯時產生結果的。它的語法如下:
sizeof (數據類型)
sizeof (表達式)
下面是兩句應用例句,程序大家可以試著編寫一下。
printf("char是多少個位元組? %bd 位元組\n",sizeof(char));
printf("long是多少個位元組? %bd 位元組\n",sizeof(long));

結果是:
char是多少個位元組? 1位元組
long是多少個位元組? 4位元組

強制類型轉換運算符
不知你們是否有自己去試著編一些程序,從中是否有遇到一些問題?初學時我就遇到過這樣一個問題:兩個不同數據類型的數在相互賦值時會出現不對的值。如下面的一段小程序:
void main(void)
{
unsigned char a;
unsigned int b;

b=100*4;
a=b;
while(1);
}
這段小程序並沒有什麼實際的應用意義,如果你是細心的朋友定會發現a的值是不會等於100*4的。是的a和b一個是char類型一個是int類型,從以前的學習可知char只佔一個位元組值最大隻能是255。但編譯時為何不出錯呢?先來看看這程序的運行情況:

圖7-8 小程序的運行情況

b=100*4就可以得知b=0x190,這時我們可以在Watches查看a的值,對於watches窗口我們在第5課時簡單學習過,在這個窗口Locals頁里可以查看程序運行中的變數的值,也可以在watch頁中輸入所要查看的變數名對它的值進行查看。做法是按圖中1的watch#1(或watch#2),然後游標移到圖中的2按F2鍵,這樣就可以輸入變數名了。在這里我們可以查看到a的值為0x90,也就是b的低8位。這是因為執行了數據類型的隱式轉換。隱式轉換是在程序進行編譯時由編譯器自動去處理完成的。所以有必要了解隱式轉換的規則:
1.變數賦值時發生的隱式轉換,"="號右邊的表達式的數據類型轉換成左邊變數的數據類型。就如上面例子中的把INT賦值給CHAR字元型變數,得到的CHAR將會是INT的低8位。如把浮點數賦值給整形變數,小數部分將丟失。
2.所有char型的操作數轉換成int型。
3.兩個具有不同數據類型的操作數用運算符連接時,隱式轉換會按以下次序進行:如有一操作數是float類型,則另一個操作數也會轉換成float類型;如果一個操作數為long類型,另一個也轉換成long;如果一個操作數是unsigned類型,則另一個操作會被轉換成unsigned類型。
從上面的規則可以大概知道有那幾種數據類型是可以進行隱式轉換的。是的,在C51中只有char,int,long及float這幾種基本的數據類型可以被隱式轉換。而其它的數據類型就只能用到顯示轉換。要使用強制轉換運算符應遵循以下的表達形式:

(類型) 表達式

用顯示類型轉換來處理不同類型的數據間運算和賦值是十分方便和方便的,特別對指針變數賦值是很有用的。看一面一段小程序:

#include <at89x51.h>
#include <stdio.h>

void main(void)
{
char xdata * XROM;
char a;
int Aa = 0xFB1C;
long Ba = 0x893B7832;
float Ca = 3.4534;
SCON = 0x50; //串口方式1,允許接收
TMOD = 0x20; //定時器1定時方式2
TH1 = 0xE8; //11.0592MHz 1200波特率
TL1 = 0xE8;
TI = 1;
TR1 = 1; //啟動定時器
XROM=(char xdata *) 0xB012; //給指針變數賦XROM初值
*XROM = 'R'; //給XROM指向的絕對地址賦值
a = *((char xdata *) 0xB012); //等同於a = *XROM
printf ("%bx %x %d %c \n",(char) Aa, (int) Ba,(int)Ca, a);//轉換類型並輸出
while(1);
}

程序運行結果:1c 7832 3 R

在上面這段程序中,可以很清楚到到各種類型進行強制類型轉換的基本用法,程序中先在外部數據存儲器XDATA中定義了一個字元型指針變數XROM,當用XROM=(char xdata *) 0xB012這一語句時,便把0xB012這個地址指針賦於了XROM,如你用XROM則會是非法的,這種方法特別適合於用標識符來存取絕對地址,如在程序前用#define ROM 0xB012這樣的語句,在程序中就可以用上面的方法用ROM對絕對地址0xB012進行存取操作了。

在附錄三中運算符的優先順序說明。

在這課的完結後,C語言中一些數據類型和運算規律已基本學習完了,下一課會開始講述語法,函數等。

示常式序下載
附 錄