1. 程式人生 > >C02 資訊儲存與運算

C02 資訊儲存與運算

目錄

  • 計算機記憶體
  • 常量和變數
  • 資料型別
  • 運算子
  • 計算機記憶體管理

  

計算機記憶體

資訊儲存概述

使用程式進行開發時,需要儲存各種資訊,這時候就需要用到變數。由於資訊型別不同,變數的型別也因此不盡相同。

同時,資訊的儲存除了用來記錄資訊之外,還會進行各種運算,因此這些運算就需要用到各種運算子。

記憶體

計算機記憶體可以分為實體記憶體和虛擬記憶體:

  • 實體記憶體:高速主儲存器
  • 虛擬記憶體:解決兩個問題:1、程式暫停,執行緒駐留在主儲存器中,可以把該程序轉移到虛擬儲存器中,提高主儲存器的使用效率;2,需要載入的程式比較大,實體記憶體容量不足。

Windows虛擬記憶體稱為:虛擬記憶體。Unix系統中稱為:(swap)交換空間。

記憶體管理

每個程式都希望程式程式碼和資料能夠更多的載入到記憶體,這樣可以提高計算機執行效率。

但是計算機都是多工系統,他需要對每個程式進行記憶體分配,這就涉及到作業系統對記憶體的管理。

常見的記憶體空間分配方式有以下三種:

分配方式

說明

特點

分頁式管理

記憶體被拆分成固定大小的儲存單位,每個單位4KB。程式申請使用記憶體時,按照4KB的倍數分配,分配區域不連續,隨機分配。

1.  頁面長度固定,分配方式簡單,記憶體利用率高。

2.  對一個程式來說,同一個邏輯模組可能被拆分為許多個頁面,不利於資訊保護和功能共享。

3.  程式在虛擬記憶體和實體記憶體之間轉移,按照4KB大小儲存單位進行轉移。

分段式管理

分段式管理主要依據程式的邏輯結構進行分段。程式邏輯結構一般分為主程式段和子程式段,主程式段必須在實體記憶體中執行,系統按照程式段的大小分配記憶體空間。段內的資料是連續的,虛擬記憶體和實體記憶體之間的轉移以段為單位進行轉移。

1.  段的長度不固定,分配空間時可能產生記憶體碎片,導致記憶體利用率不足。

2.  對一個程式來說,同一個邏輯模組連續存放,不僅提高了執行效率,也便於資訊的保護和功能共享。

段頁式管理

大多數計算機結合了分頁式儲存和分段式管理的優點,採用段頁式的管理。

1.  先將程式按邏輯模組分段,每個段再進行分頁,資訊傳遞以頁為單位。

2.  建立相關聯的段表、頁表,用來定位程式段、段內各業的儲存地址。

3.  通過分段提高了程式執行效率,通過分頁改善了記憶體空間的利用率。

 

 

常量和變數

C語言基本元素

1. 符號集(字符集)

C語言基本字符集分為源字符集(書寫C語言原始檔所用的字符集)和執行字符集(C語言程式執行期間解釋的字符集)。

源字符集包括大小寫字母(52)、數字(10)、格式符(4)、特殊字元(29)。

執行字符集在源字符集的基礎上還包括null字元(用做字串終止符)、警報(alert)、退格(backspace)、回車(carriage return)。為了在字母和字串中表示這些字元,輸入反斜槓\加對應的轉義序列(escape sequence)即可,例如,\0表示 null 字元(空字元),\a表示警報,\b表示退格,而\r表示回車。

源字符集中,格式符包括:空格、水平製表符(HT)、垂直製表符(VT)、換頁符(FF)。特殊字元如下29個:

!  "  #  %  &  '  ( )  *  +  , - .  /  : ;  

<  =  >  ?  [  \  ]  ^  _  {  |  }  ~

 

 

2. 關鍵字

也稱為保留字,是C語言中具有特定含義,專門用作語言特定成分的一類識別符號。ANSI標準定義32個關鍵字。

非常見:auto、register、volatile、goto。

儲存相關:const、extern、register、volatile、static、auto、signed、unsigned。

資料型別:char、short、int、float、long、double、struct、union、enum、void。

邏輯控制:if、else、for、while、do、break、continue、return、default、switch、case、goto。

特殊用途:sizeof、typedef

注意: 我們定義的識別符號不能是關鍵字;所有關鍵字小寫。

 

3. 識別符號

用來標記常量、變數、函式及檔名字的一串字元。(不包括關鍵字)。

識別符號命名規則:

1)        以字母(大小寫都可以)或下劃線開頭;

2)        後可跟若干個(包括0個)字母、數字、下劃線;

3)        識別符號的長度在各種編譯器和系統有所不同,建議不超過8個字元;

4)        識別符號與關鍵字不能相同。

問題?以下那些是合法的識別符號,哪些是非法的?

x

y3

_imax

ELSE

X

A_to_B

7x

int

#NO

bad one

re-input

aaaabbbbccc

 

 

常量和變數

程式所操作的資訊需要儲存在記憶體中,所以需要定義常量和變數,常量和變數儲存所需操作的資訊。

1.      常量

常量:指在程式執行過程中,其值不變的量。在程式中不必對常量進行任何說明就可以使用。

例如:人的性別,一生下來就確定,不可以修改,即常量。

2.      變數

變數:指在程式執行過程中,其值可以被改變的量。

例如:人的姓名,或者小名,可以改變,即變數。

對於C語言來說,變數的值=該儲存空間裡的資料和資訊。

變數的定義

語法規則:

資料型別  識別符號1 [,識別符號2,…識別符號N ] ;

例如:

       int a;

  char b,c;

    命名規則:與識別符號命名規則一致。

 

3.      常量與變數命名規範

1)        區分大小寫

2)        命名要見名知意

3)        先定義後使用

4)        符號常量名用大寫,變數小寫

 

4.      變數的賦值

1)        定義變數時初始化變數值

資料型別  變數名=初始值;

2)        先定義變數,然後為變數賦值

資料型別  變數名;

變數名=初始值;

 

5.      變數的輸入和輸出

scanf(“%d”,&a);

printf(“%d”,a);

 

6.      變數的使用

變數型別決定了變數在記憶體中的地址分配;變數名即變數在記憶體中的地址。

 

資料型別

C語言資料型別

c語言型別主要分為四類:

序號

型別與描述

1

基本型別:
它們是算術型別,包括兩種型別:整數型別和浮點型別。

2

列舉型別:
它們也是算術型別,被用來定義在程式中只能賦予其一定的離散整數值的變數。

3

void 型別:
型別說明符 void 表明沒有可用的值。

4

派生型別:
它們包括:指標型別、陣列型別、結構型別、共用體型別和函式型別。

基本型別

基本型別資料如下:

型別

儲存大小

值範圍

char

1 位元組

-128 到 127 或 0 到 255

unsigned char

1 位元組

0 到 255

signed char

1 位元組

-128 到 127

int

2 或 4 位元組

-32,768 到 32,767 或 -2,147,483,648 到 2,147,483,647

unsigned int

2 或 4 位元組

0 到 65,535 或 0 到 4,294,967,295

short

2 位元組

-32,768 到 32,767

unsigned short

2 位元組

0 到 65,535

long

4 位元組

-2,147,483,648 到 2,147,483,647

unsigned long

4 位元組

0 到 4,294,967,295

1.      字元型資料

字元常量:用單引號包含的一個字元,只能包含一個字元。

例如:

‘a’         ‘A’       ‘$’

轉義字元:特殊的常量字元,詳細參考第一章介紹。

字元變數:字元型變數用來存放字元常量,只能存放一個字元。一個字元變數在記憶體中佔用一個位元組。

字元變數的定義和賦值:字元變數的賦值可以是直接賦值字元常量,或者整數(整數必須在ASCII表示範圍內)。如下示例所示:

 

 

字元資料在記憶體中的儲存

 

 

2.      整型資料

整型的儲存大小與系統位數有關,int資料型別的數值範圍與系統有關,16、32、64位系統對應預設整型資料的長度分別是16、32、64位。但目前通用的以64位系統為主。以下列出了32位系統與64位系統的儲存大小的差別(windows 相同):

 

使用 sizeof 運算子判斷具體平臺的儲存大小。表示式:sizeof(type) 得到物件或型別的儲存位元組大小。如下示例示例:

 

其中,%lu 為 32 位無符號整數。

 

整型變數在記憶體中的表示:以十進位制數13示例示例。

 

如何表示負數?C語言中負數是以補碼的形式進行儲存的。計算機中的符號數有三種表示方法,即原碼、反碼和補碼。三種表示方法均有符號位和數值位兩部分,符號位都是用0表示“正”,用1表示“負”,而數值位,三種表示方法各不相同:正整數的補碼是其二進位制表示,與原碼相同;負整數的補碼,將其對應正數二進位制表示所有位取反(包括符號位,0變1,1變0)後加1。

<<參考計算機補碼及運算>>

  

3.      浮點型別

型別

儲存大小

值範圍

精度

float

4 位元組

1.2E-38 到 3.4E+38

6 位小數

double

8 位元組

2.3E-308 到 1.7E+308

15 位小數

long double

16 位元組

3.4E-4932 到 1.1E+4932

19 位小數

 

標頭檔案 float.h 定義了巨集,在程式中可以使用這些值和其他有關實數二進位制表示的細節。下面的例項將輸出浮點型別佔用的儲存空間以及它的範圍值:

 

%E 為以指數形式輸出單、雙精度實數。

 

void型別

void 型別指定沒有可用的值。它通常用於以下三種情況下:

序號

型別與描述

1

函式返回為空
C 中有各種函式都不返回值,或者您可以說它們返回空。不返回值的函式的返回型別為空。例如 void exit (int status);

2

函式引數為空
C 中有各種函式不接受任何引數。不帶引數的函式可以接受一個 void。例如 int rand(void);

3

指標指向 void
型別為 void * 的指標代表物件的地址,而不是型別。例如,記憶體分配函式 void *malloc( size_t size ); 返回指向 void 的指標,可以轉換為任何資料型別。

 

 

運算子

運算子是一種告訴編譯器執行特定的數學或邏輯操作的符號。C 語言內建了豐富的運算子,並提供了以下型別的運算子:

 

算術運算子

下表顯示了 C 語言支援的所有算術運算子。假設變數 A 的值為 10,變數 B 的值為 20,則:

運算子

描述

例項

+

把兩個運算元相加

A + B 將得到 30

-

從第一個運算元中減去第二個運算元

A - B 將得到 -10

*

把兩個運算元相乘

A * B 將得到 200

/

分子除以分母

B / A 將得到 2

%

取模運算子,整除後的餘數

B % A 將得到 0

++

自增運算子,整數值增加 1

A++ 將得到 11

--

自減運算子,整數值減少 1

A-- 將得到 9

 

 

關係運算符

下表顯示了 C 語言支援的所有關係運算符。假設變數 A 的值為 10,變數 B 的值為 20,則:

運算子

描述

例項

==

檢查兩個運算元的值是否相等,如果相等則條件為真。

(A == B) 不為真

!=

檢查兩個運算元的值是否相等,如果不相等則條件為真。

(A != B) 為真

檢查左運算元的值是否大於右運算元的值,如果是則條件為真。

(A > B) 不為真

檢查左運算元的值是否小於右運算元的值,如果是則條件為真。

(A < B) 為真

>=

檢查左運算元的值是否大於或等於右運算元的值,如果是則條件為真。

(A >= B) 不為真

<=

檢查左運算元的值是否小於或等於右運算元的值,如果是則條件為真。

(A <= B) 為真

邏輯運算子

下表顯示了 C 語言支援的所有關係邏輯運算子。假設變數 A 的值為 1,變數 B 的值為 0,則:

運算子

描述

例項

&&

稱為邏輯與運算子。如果兩個運算元都非零,則條件為真。

(A && B) 為假。

||

稱為邏輯或運算子。如果兩個運算元中有任意一個非零,則條件為真。

(A || B) 為真。

!

稱為邏輯非運算子。用來逆轉運算元的邏輯狀態。如果條件為真則邏輯非運算子將使其為假。

!(A && B) 為真。

邏輯運算子&&和||存在短路運算,示例如下:

int main()

{

       int a=10;

       int b=11;

       int c=0;

       if(a==b&&c++){

      

       }

       printf("%d",c);

       return 0;

}

或者

int main()

{

       int a=10;

       int b=10;

       int c=0;

       if(a==b||c++){

      

       }

       printf("%d",c);

       return 0;

}

 

以上程式碼各輸出c的結果是?(輸出為:0)

位運算子

假設如果 A = 60,且 B = 13,現在以二進位制格式表示,它們如下所示:

A = 0011 1100

B = 0000 1101

-----------------

A&B = 0000 1100

A|B = 0011 1101

A^B = 0011 0001

~A  = 1100 0011

 

位運算子作用於二進位制位,並逐位執行操作。&、 | 和 ^ 的真值表如下所示:

運算子

描述

例項

&

按位與操作,按二進位制位進行"與"運算。運算規則:

0&0=0;  

0&1=0;   

1&0=0;    

1&1=1;

(A & B) 將得到 12,即為 0000 1100

|

按位或運算子,按二進位制位進行"或"運算。運算規則:

0|0=0;  

0|1=1;  

1|0=1;   

1|1=1;

(A | B) 將得到 61,即為 0011 1101

^

異或運算子,按二進位制位進行"異或"運算。運算規則:

0^0=0;  

0^1=1;  

1^0=1; 

1^1=0;

(A ^ B) 將得到 49,即為 0011 0001

~

取反運算子,按二進位制位進行"取反"運算。運算規則:

~1=0;  

~0=1;

(~A ) 將得到 -61,即為 1100 0011,一個有符號二進位制數的補碼形式。

<< 

二進位制左移運算子。將一個運算物件的各二進位制位全部左移若干位(左邊的二進位制位丟棄,右邊補0)。

A << 2 將得到 240,即為 1111 0000

>> 

二進位制右移運算子。將一個數的各二進位制位全部右移若干位,正數左補0,負數左補1,右邊丟棄。

A >> 2 將得到 15,即為 0000 1111

 

示例程式碼:

#include <stdio.h>

 

int main()

{

  unsigned int a = 60;    /* 60 = 0011 1100 */ 

   unsigned int b = 13;    /* 13 = 0000 1101 */

   int c = 0;          

 

   c = a & b;       /* 12 = 0000 1100 */

   printf("Line 1 - c 的值是 %d\n", c );

 

   c = a | b;       /* 61 = 0011 1101 */

   printf("Line 2 - c 的值是 %d\n", c );

 

   c = a ^ b;       /* 49 = 0011 0001 */

   printf("Line 3 - c 的值是 %d\n", c );

 

   c = ~a;          /*-61 = 1100 0011 */

   printf("Line 4 - c 的值是 %d\n", c );

 

   c = a << 2;     /* 240 = 1111 0000 */

   printf("Line 5 - c 的值是 %d\n", c );

 

   c = a >> 2;     /* 15 = 0000 1111 */

   printf("Line 6 - c 的值是 %d\n", c );

}

輸出結果

 

 

賦值運算子

下表列出了 C 語言支援的賦值運算子:

運算子

描述

例項

=

簡單的賦值運算子,把右邊運算元的值賦給左邊運算元

C = A + B 將把 A + B 的值賦給 C

+=

加且賦值運算子,把右邊運算元加上左邊運算元的結果賦值給左邊運算元

C += A 相當於 C = C + A

-=

減且賦值運算子,把左邊運算元減去右邊運算元的結果賦值給左邊運算元

C -= A 相當於 C = C - A

*=

乘且賦值運算子,把右邊運算元乘以左邊運算元的結果賦值給左邊運算元

C *= A 相當於 C = C * A

/=

除且賦值運算子,把左邊運算元除以右邊運算元的結果賦值給左邊運算元

C /= A 相當於 C = C / A

%=

求模且賦值運算子,求兩個運算元的模賦值給左邊運算元

C %= A 相當於 C = C % A

<<=

左移且賦值運算子

C <<= 2 等同於 C = C << 2

>>=

右移且賦值運算子

C >>= 2 等同於 C = C >> 2

&=

按位與且賦值運算子

C &= 2 等同於 C = C & 2

^=

按位異或且賦值運算子

C ^= 2 等同於 C = C ^ 2

|=

按位或且賦值運算子

C |= 2 等同於 C = C | 2

 

雜項運算子

下表列出了 C 語言支援的其他一些重要的運算子,包括 sizeof 和 ? :。

運算子

描述

例項

sizeof()

返回變數的大小。

sizeof(a) 將返回 4,其中 a 是整數。

&

返回變數的地址。

&a; 將給出變數的實際地址。

*

指向一個變數。

*a; 將指向一個變數。

? :

條件表示式

如果條件為真 ? 則值為 X : 否則值為 Y

示例程式碼:

#include <stdio.h>

 

int main()

{

   int a = 4;

   short b;

   double c;

   int* ptr;

 

   /* sizeof 運算子例項 */

   printf("Line 1 - 變數 a 的大小 = %lu\n", sizeof(a) );

   printf("Line 2 - 變數 b 的大小 = %lu\n", sizeof(b) );

   printf("Line 3 - 變數 c 的大小 = %lu\n", sizeof(c) );

 

   /* & 和 * 運算子例項 */

   ptr = &a;    /* 'ptr' 現在包含 'a' 的地址 */

   printf("a 的值是 %d\n", a);

   printf("*ptr 是 %d\n", *ptr);

 

   /* 三元運算子例項 */

   a = 10;

   b = (a == 1) ? 20: 30;

   printf( "b 的值是 %d\n", b );

 

   b = (a == 10) ? 20: 30;

   printf( "b 的值是 %d\n", b );

}

  

 輸出結果:

 

 

運算子優先順序

運算子的優先順序確定表示式中項的組合。這會影響到一個表示式如何計算。某些運算子比其他運算子有更高的優先順序,例如,乘除運算子具有比加減運算子更高的優先順序。

例如 x = 7 + 3 * 2,在這裡,x 被賦值為 13,而不是 20,因為運算子 * 具有比 + 更高的優先順序,所以首先計算乘法 3*2,然後再加上 7。

下表將按運算子優先順序從高到低列出各個運算子,具有較高優先順序的運算子出現在表格的上面,具有較低優先順序的運算子出現在表格的下面。在表示式中,較高優先順序的運算子會優先被計算。

類別 

運算子 

結合性 

字尾 

() [] -> . ++ - -  

從左到右 

一元 

+ - ! ~ ++ - - (type)* & sizeof 

從右到左 

乘除 

* / % 

從左到右 

加減 

+ - 

從左到右 

移位 

<< >> 

從左到右 

關係 

< <= > >= 

從左到右 

相等 

== != 

從左到右 

位與 AND 

從左到右 

位異或 XOR 

從左到右 

位或 OR 

從左到右 

邏輯與 AND 

&& 

從左到右 

邏輯或 OR 

|| 

從左到右 

條件 

?: 

從右到左 

賦值 

= += -= *= /= %=>>= <<= &= ^= |= 

從右到左 

逗號 

從左到右