1. 程式人生 > >C語言基礎學習day04

C語言基礎學習day04

運算子、表示式和語句

迴圈簡介

#include <stdio.h>
#define ADJUST 7.31
int main(void)
{
    const double SCALE=0.333;
    double shoe,foot;
    printf("Shoe size (men's) foot length\n");
    shoe=3.0;
    while(shoe<18.5)
    {
        foot=SCALE*shoe+ADJUST;
        printf("%10.1f %15.2f inches\n
",shoe,foot); shoe=shoe+1.0; } printf("if the shoe fits,wear it.\n"); return 0; }

當程式第一次到達while迴圈時,會檢查圓括號中的條件是否為真,條件為真,程式進入塊中繼續執行,把尺碼轉換成英寸

然後列印計算的 結果。下一條語句把 shoe增加1.0,使shoe的值為4.0:

shoe = shoe + 1.0;
此時,程式返回while入口部分檢查條件。

為何要返回while的入口部分?因為上面這條語句的下面是右花括號(}),程式碼使用一對花括號 ({})來標出while迴圈的範圍。花括號之間的內容就是要被重複執行的內 容。花括號以及被花括號括起來的部分被稱為塊(block)。現在,回到程式中。因為4小於18.5,所以要重複執行被花括號括起來的所有內容(用計算機術語來說就是,程式迴圈這些語句)。該迴圈過程一直持續到shoe的值為19.0。此時,由於19.0小於18.5,所以該條件為假:
shoe < 18.5
出現這種情況後,控制轉到緊跟while迴圈後面的第1條語句。該例中, 是最後的printf()語句。

 

基本運算子

賦值運算子:=

在編寫程式碼時要記住,=號左側的項必須是一個變數名。實際上,賦值運算子左側必須引用一個儲存位置。最簡單的方法就是使用變數名。不過,後面章節還會介紹“指標”,可用於指向一個儲存位置。概括地說,C 使用可修改的左值(modifiable lvalue) 標記那些可賦值的實體。

“項”(如,賦值運算子左側的項)的就是運算物件(operand)。運算物件是運算子操作的物件。例如,可以把吃漢堡描述 為:“吃”運算子操作“漢堡”運算物件。類似地可以說,=運算子的左側運算物件應該是可修改的左值

#include<stdio.h>
int
main(void) { int jane,tarzan,cheeta; cheeta =tarzan =jane =68; printf(" cheeta tarzan jane\n"); printf("first round score %4d %8d %8d\n",cheeta,tarzan,jane); return 0; }

許多其他語言都會迴避該程式中的三重賦值,但是C完全沒問題。賦值 的順序是從右往左:首先把86賦給jane,然後再賦給tarzan,最後賦給 cheeta

執行結果:

cheeta tarzan jane
first round score 68 68 68

 

加法運算子:+

加法運算子(addition operator)用於加法運算,使其兩側的值相加。例如,語句:

printf("%d", 4 + 20);

列印的是24,而不是表示式
4 + 20
相加的值(運算物件)可以是變數,也可以是常量。

 

乘法運算子:*

該程式列印數字1~20及其平方

#include<stdio.h>
int main(void)
{
    int num=1;
    while (num <21)
    {
        printf("%4d%6d\n",num,num*num);
        num=num+1;
    }
    return 0;
}

 

#include<stdio.h>
#define SQUARES 64
int main(void) 
{
    const double CROP =2E16;
    double current,total;
    int count =1;
    printf("square   grains   total    ");
    printf("fraction  of  \n");
    printf("added     grain     ");
    printf("world             total\n");
    total=current=1.0;
    printf("%4d %13.2e %12.2e %12.2e\n", count,current,total,total/CROP);

    while (count<SQUARES)
    {
        count=count+1;
        current=2.0*current;
        total=total+current;
        printf("%4d %13.2e %12.2e %12.2e\n",count,current,total,total/CROP);
    } 
    printf("That's all.\n");
    
    return 0;
}

當遇到error: stray '\241' in program錯誤的解決方法:該錯誤是指源程式中有非法字元,需要將非法字元去掉。一般是由於coder使用中文輸入法或者從別的地方直接複製貼上程式碼造成的。程式碼中出現了中文空格,中文引號, 各種中文標點符號都會出現,簡單修改一下就OK了

 

除法運算子:/

#include<stdio.h>
int main(void)
{
    printf("integer division:5/4 is %d\n",5/4);
    printf("integer division:6/3 is %d\n",6/3);
    printf("integer division:7/4 is %d\n",7/4);
    printf("floating division: 7./4. is %1.2f\n",7./4.);
    printf("mixed division:7./4 is %1.2f\n",7./4);
    return 0;

}

執行結果:

注意,整數除法會截斷計算結果的小數部分(丟棄整個小數部分),不 會四捨五入結果。混合整數和浮點數計算的結果是浮點數。

實際上,計算機不能真正用浮點數除以整數,編譯器會把兩個運算物件轉換成相同的型別。 本例中,在進行除法運算前,整數會被轉換成浮點數。

C99標準以前,C語言給語言的實現者留有一些空間,讓他們來決定如何進行負數的整數除法。一種方法是,舍入過程採用小於或等於浮點數的最大整數。當然,對於3.8而言,處理後的3符合這一描述。但是-3.8 會怎樣? 該方法建議四捨五入為-4,因為-4 小

於-3.8.但是,另一種舍入方法是直接丟 棄小數部分。這種方法被稱為“趨零截斷”,即把-3.8轉換成-3。在C99以前, 不同的實現採用不同的方法。但是C99規定使用趨零截斷。所以,應把-3.8 轉換成-3

 

運算子優先順序

#include<stdio.h>
int main(void)
{
    int top,score;
    top=score=-(2+5)*6+(4+3*(2+3));
    printf("top = %d,score = %d\n",top,score);
    return 0;
}

輸出結果:-23

 

sizeof運算子和size_t型別

sizeof運算子以位元組為單 位返回運算物件的大小(在C中,1位元組定義為char型別佔用的空間大小。過去,1位元組通常是8位,但是一些字符集可能使用更大的位元組

#include<stdio.h>
int main(void)
{
    int n = 0;
    size_t intsize;
    intsize = sizeof(int);
    printf("n = %d, n has %zd bytes; all ints have %zd bytes.\n",n,sizeof n,intsize);
    
    return 0;
}

執行結果:

n = 0, n has 4 bytes; all ints have 4 bytes.

C 語言規定,sizeof 返回 size_t 型別的值。這是一個無符號整數型別, 但它不是新型別,size_t是語言定義的標準型別

C有一個 typedef機制,允許程式設計師為現有型別建立別名。例如,

typedef double real;

這樣,real就是double的別名。現在,可以宣告一個real型別的變數:
real deal; // 使用typedef

編譯器檢視real時會發現,在typedef宣告中real已成為double的別名,於是把deal建立為double 型別的變數。類似地,C 標頭檔案系統可以使用 typedef 把 size_t 作為 unsigned int 或unsigned long的別名。這樣,在使用size_t型別 時,編譯器會根據不同的系統替換標準型別

 

求模運算子:%

負數求模如何進行?C99規定“趨零截斷”之前,該問題的處理方法很 多。但自從有了這條規則之後,如果第1個運算物件是負數,那麼求模的結 果為負數;如果第1個運算物件是正數,那麼求模的結果也是正數:
11 / 5得2,11 % 5得1
11 / -5得-2,11 % -2得1
-11 / -5得2,-11 % -5得-1
-11 / 5得-2,-11 % 5得-1
如果當前系統不支援C99標準,會顯示不同的結果。實際上,標準規 定:無論何種情況,只要a和b都是整數值,便可通過a - (a/b)*b來計算a%b。

例如,可以這樣計算-11%5:

-11 - (-11/5) * 5 = -11 -(-2)*5 = -11 -(-10) = -1

 

 

 遞增運算子:++

該運算子以兩種方式出現:

第1種方式,++出現在其作用的變數前面, 這是字首模式;

第2種方式,++出現在其作用的變數後面,這是字尾模式。

#include<stdio.h>
int main(void)
{
    int a=1,b=1;
    int a_post,pre_b;
    a_post=a++;//字尾遞增 
    pre_b=++b;//字首遞增
    printf("a   a_post    b   pre_b   \n");
    printf("%1d  %5d  %5d  %5d\n",a,a_post,b,pre_b);
    return 0; 
}

執行結果:

a和b都遞增了1,但是,a_post是a遞增之前的值,而b_pre是b遞增之後 的值。這就是++的字首形式和字尾形式的區別

 

x*y++表示的是(x)*(y++),而不是(x+y)++。不過後者無 效,因為遞增和遞減運算子只能影響一個變數(或者,更普遍地說,只能影 響一個可修改的左值),而組合x*y本身不是可修改的左值。

不要混淆這兩個運算子的優先順序和它們的求值順序。假設有如下語句:

y = 2;
n = 3;
nextnum = (y + n++)*6;
nextnum的值是多少?把y和n的值帶入上面的第3條語句得:
nextnum = (2 + 3)*6 = 5*6 = 30
n的值只有在被使用之後才會遞增為4。根據優先順序的規定,++只作用 於n,不作用與y + n。除此之外,根據優先順序可以判斷何時使用n的值對錶達 式求值,而遞增運算子的性質決定了何時遞增n的值。

如果n++是表示式的一部分,可將其視為“先使用n,再遞增”;而++n則表示“先遞增n,再使用”。

 

表示式和語句

表示式

表示式(expression)由運算子和運算物件組成(運算物件是運算子操作的物件)。最簡單的表示式是一個單獨的運算物件,以此為基礎可以建立複雜的表示式

運算物件可以是常量、變數或二者的組合。一些表示式由子 表示式(subexpression)組成(子表示式即較小的表示式)

 

語句

語句(statement)是C程式的基本構建塊。一條語句相當於一條完整的 計算機指令。在C中,大部分語句都以分號結尾 

語句可分為簡單語句和複合語句。簡單語句以一個分號結尾。

如下所示:

賦值表示式語句:   toes = 12;
函式表示式語句:   printf("%d\n", toes);
空語句:          ;  /* 什麼也不做 */
複合語句(或塊)由花括號括起來的一條或多條語句組成。

如下面的 while語句所示:
  while (years < 100)
  {
    wisdom = wisdom * 1.05;
    printf("%d %d\n", years, wisdom);
    years = years + 1;
  }

 

 

型別轉換

基本的型別轉換規則

1.當型別轉換出現在表示式時,無論是unsigned還是signed的char和short 都會被自動轉換成int,如有必要會被轉換成unsigned int(如果short與int的大 小相同,unsigned short就比int大。這種情況下,unsigned short會被轉換成 unsigned int)。

   在K&R那時的C中,float會被自動轉換成double(目前的C不是這樣)。由於都是從較小型別轉換為較大型別,所以這些轉換被稱為升級 (promotion)。

2.涉及兩種型別的運算,兩個值會被分別轉換成兩種型別的更高級別。

3.型別的級別從高至低依次是long double、double、float、unsignedlong long、long long、unsigned long、long、unsigned int、int。例外的情況是,當 long 和 int 的大小相同時,unsigned int比long的級別高。

  之所以short和char型別沒有列出,是因為它們已經被升級到int或unsigned int。

4.在賦值表示式語句中,計算的最終結果會被轉換成被賦值變數的類 型。這個過程可能導致型別升級或降級(demotion)。所謂降級,是指把一 種類型轉換成更低級別的型別。

5.當作為函式引數傳遞時,char和short被轉換成int,float被轉換成 double。函式原型會覆蓋自動升級。
   型別升級通常都不會有什麼問題,但是型別降級會導致真正的麻煩。原因很簡單:較低型別可能放不下整個數字。例如,一個8位的char型別變數儲存整數101沒問題,但是存不下22334。

 

待賦值的值與目標型別不匹配時規則

1.目標型別是無符號整型,且待賦的值是整數時,額外的位將被忽略。 例如,如果目標型別是 8 位unsigned char,待賦的值是原始值求模256。
2.如果目標型別是一個有符號整型,且待賦的值是整數,結果因實現而異。
3.如果目標型別是一個整型,且待賦的值是浮點數,該行為是未定義的