程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C++從零開始(六)何謂語句

C++從零開始(六)何謂語句

編輯:C++入門知識

  前面已經說過程序就是方法的描述,而方法的描述無外乎就是動作加動作的賓語,而這裡的動作在C++中就是通過語句來表現的,而動作的賓語,也就是能夠被操作的資源,但非常可惜地C++語言本身只支持一種資源——內存。由於電腦實際可以操作不止內存這一種資源,導致C++語言實際並不能作為底層硬件程序的編寫語言(即使是C語言也不能),不過各編譯器廠商都提供了自己的嵌入式匯編語句功能(也可能沒提供或提供其它的附加語法以使得可以操作硬件),對於VC,通過使用__asm語句即可實現在C++代碼中加入匯編代碼來操作其他類型的硬件資源。對於此語句,本系列不做說明。

  語句就是動作,C++中共有兩種語句:單句和復合語句。復合語句是用一對大括號括起來,以在需要的地方同時放入多條單句,如:{ long a = 10; a += 34; }。而單句都是以“;”結尾的,但也可能由於在末尾要插入單句的地方用復合語句代替了而用“}”結尾,如:if( a ) { a--; a++; }。應注意大括號後就不用再寫“;”了,因為其不是單句。

  方法就是怎麼做,而怎麼做就是在什麼樣的情況下以什麼樣的順序做什麼樣的動作。因為C++中能操作的資源只有內存,故動作也就很簡單的只是關於內存內容的運算和賦值取值等,也就是前面說過的表達式。而對於“什麼樣的順序”,C++強行規定只能從上朝下,從左朝右來執行單句或復合語句(不要和前面關於表達式的計算順序搞混了,那只是在一個單句中的規則)。而最後對於“什麼樣的情況”,即進行條件的判斷。為了不同情況下能執行不同的代碼,C++定義了跳轉語句來實現,其是基於CPU的運行規則來實現的,下面先來看CPU是如何執行機器代碼的。

  機器代碼的運行方式

  前面已經說過,C++中的所有代碼到最後都要變成CPU能夠認識的機器代碼,而機器代碼由於是方法的描述也就包含了動作和動作的賓語(也可能不帶賓語),即機器指令和內存地址或其他硬件資源的標識,並且全部都是用二進制數表示的。很正常,這些代表機器代碼的二進制數出於效率的考慮在執行時要放到內存中(實際也可以放在硬盤或其他存儲設備中),則很正常地每個機器指令都能有一個地址和其相對應。

  CPU內帶一種功能和內存一樣的用於暫時記錄二進制數的硬件,稱作寄存器,其讀取速度較內存要快很多,但大小就小許多了。為了加快讀取速度,寄存器被去掉了尋址電路進而一個寄存器只能存放1個32位的二進制數(對於32位電腦)。而CPU就使用其中的一個寄存器來記錄當前欲運行的機器指令的位置,在此稱它為指令寄存器。

  CPU運行時,就取出指令寄存器的值,進而找到相應的內存,讀取1個字節的內容,查看此8位二進制數對應的機器指令是什麼,進而做相應的動作。由於不同的指令可能有不同數量的參數(即前面說的動作的賓語)需要,如乘法指令要兩個參數以將它們乘起來,而取反操作只需要一個參數的參與。並且兩個8位二進制數的乘法和兩個16位二進制數的乘法也不相同,故不同的指令帶不同的參數而形成的機器代碼的長度可能不同。每次CPU執行完某條機器代碼後,就將指令寄存器的內容加上此機器代碼的長度以使指令寄存器指向下一條機器代碼,進而重復上面的過程以實現程序的運行(這只是簡單地說明,實際由於各種技術的加入,如高速緩沖等,實際的運行過程要比這復雜得多)。

  語句的分類

  在C++中,語句總共有6種:聲明語句、定義語句、表達式語句、指令語句、預編譯語句和注釋語句。其中的聲明語句下篇說明,預編譯語句將在另文中說明,而定義語句就是前面已經見過的定義變量,後面還將說明定義函數、結構等。表達式語句則就是一個表達式直接接一個“;”,如:34;、a = 34;等,以依靠操作符的計算功能的定義而生成相應的關於內存值操作的代碼。注釋語句就是用於注釋代碼的語句,即寫來給人看的,不是給編譯器看的。最後的指令語句就是含有下面所述關鍵字的語句,即它們的用處不是操作內存,而是實現前面說的“什麼樣的情況”。

  這裡的聲明語句、預編譯語句和注釋語句都不會轉換成機器代碼,即這三種語句不是為了操作電腦,而是其他用途,以後將詳述。而定義語句也不一定會生成機器代碼,只有表達式語句和指令語句一定會生成代碼(不考慮編譯器的優化功能)。

  還應注意可以寫空語句,即;或{},它們不會生成任何代碼,其作用僅僅只是為了保證語法上的正確,後面將看到這一點。下面說明注釋語句和指令語句——跳轉語句、判斷語句和循環語句(實際不止這些,由於異常和模板技術的引入而增加了一些語句,將分別在說明異常和模板時說明)。

  注釋語句——//、/**/

  注釋,即用於解釋的標注,即一些文字信息,用以向看源代碼的人解釋這段代碼什麼意思,因為人的認知空間和電腦的完全不同,這在以後說明如何編程時會具體討論。要書寫一段話用以注釋,用“/*”和“*/”將這段話括起來,如下:

long a = 1;
a += 1; /* a放的是人的個數,讓人的個數加一 */
b *= a; /* b放的是人均花費,得到總的花費 */

  上面就分別針對a += 1;和b *= a;寫了兩條注釋語句以說明各自的語義(因為只要會C++都知道它們是一個變量的自增一和另一個變量的自乘a,但不知道意義)。上面的麻煩之處就是需要寫“/*”和“*/”,有點麻煩,故C++又提供了另一種注釋語句——“//”:

long a = 1;
a += 1; // a放的是人的個數,讓人的個數加一
b *= a; // b放的是人均花費,得到總的花費

  上面和前面等效,其中的“//”表示從它開始,這一行後面的所有字符均看成注釋,編譯器將不予理會,即

long a = 1; a += 1; // a放的是人的個數,讓人的個數加一 b *= a;
  其中的b *= a;將不會被編譯,因為前面的“//”已經告訴編譯器,從“//”開始,這一行後面的所有字符均是注釋,故編譯器不會編譯b *= a;。但如果

long a = 1; a += 1; /* a放的是人的個數,讓人的個數加一 */ b *= a;
  這樣編譯器依舊會編譯b *= a;,因為“/*”和“*/”括起來的才是注釋。

  應該注意注釋語句並不是語句,其不以“;”結束,其只是另一種語法以提供注釋功能,就好象以後將要說明的預編譯語句一樣,都不是語句,都不以“;”結束,既不是單句也不是復合語句,只是出於習慣的原因依舊將它們稱作語句。

  跳轉語句——goto

  前面已經說明,源代碼(在此指用C++編寫的代碼)中的語句依次地轉變成用長度不同的二進制數表示的機器代碼,然後順序放在內存中(這種說法不准確)。如下面這段代碼:

long a = 1; // 假設長度為5字節,地址為3000
a += 1; // 則其地址為3005,假設長度為4字節
b *= a; // 則其地址為3009,假設長度為6字節

  上面的3000、3005和3009就表示上面3條語句在內存中的位置,而所謂的跳轉語句,也就是將上面的3000、3005等語句的地址放到前面提過的指令寄存器中以使得CPU開始從給定的位置執行以表現出執行順序的改變。因此,就必須有一種手段來表現語句的地址,C++對此給出了標號(Label)。

  寫一標識符,後接“:”即建立了一映射,將此標識符和其所在位置的地址綁定了起來,如下:

long a = 1; // 假設長度為5字節,地址為3000
P1:
a += 1; // 則其地址為3005,假設長度為4字節
P2:
b *= a; // 則其地址為3009,假設長度為6字節
goto P2;

  上面的P1和P2就是標號,其值分別為3005和3009,而最後的goto就是跳轉語句,其格式為goto <標號>;。此語句非常簡單,先通過“:”定義了一個標號,然後在編寫goto時使用不同的標號就能跳到不同的位置。

  應該注意上面故意讓P1和P2定義時獨占一行,其實也可以不用,即:

long a = 1;
P1: a += 1;
P2: b *= a;
goto P2;

  因此看起來“P1:”和“P2:”好象是單獨的一條定義語句,應該注意,准確地說它們應該是語句修飾符,作用是定義標號,並不是語句,即這樣是錯誤的:

long a = 1;
P1: {
 a += 1;
 P2: b *= a;
 P3:
} goto P2;

  上面的P3:將報錯,因為其沒有修飾任何語句。還應注意其中的P1仍然是3005,即“{}”僅僅只是其復合的作用,實際並不產生代碼進而不影響語句的地址。

  判斷語句——if else、switch

  if else 前面說過了,為了實現“什麼樣的情況”做“什麼樣的動作”,故C++非常正常地提供了條件判斷語句以實現條件的不同而執行不同的代碼。if else的格式為:

if(<數字>)<語句1>else<語句2> 或者 if(<數字>)<語句1>
long a = 0, b = 1;
P1:
a++;
b *= a;
if( a < 10 )
goto P1;
long c = b;

  上面的代碼就表示只有當a的值小於10時,才跳轉到P1以重復執行,最後的效果就是c的值為10的階乘。

  上面的<數字>表示可以在“if”後的括號中放一數字,即表達式,而當此數字的值非零時,即邏輯真,程序跳轉以執行<語句1>,如果為零,即邏輯假,則執行<語句2>。即也可如此:if( a – 10 ) goto P1;,其表示當a – 10不為零時才執行goto P1;。這和前面的效果一樣,雖然最後c仍然是10的階乘,但意義不同,代碼的可讀性下降,除非出於效率的考慮,不推薦如此書寫代碼。

  而<語句1>和<語句2>由於是語句,也就可以放任何是語句的東西,因此也可以這樣:

if( a ) long c;
  上面可謂吃飽了撐了,在此只是為了說明<語句1>實際可以放任何是語句的東西,但由於前面已經說過,標號的

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved