程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C語言要點

C語言要點

編輯:關於C語言

一關鍵字:

1.       static:

第一個作用:修飾變量。變量又分為局部和全局變量,但它們都存在內存的靜態區。由於被 static修飾的變量總是存在內存的靜態區,所以即使這個函數運行結束,這個靜態變量的值還是不會被銷毀,函數下次使用時仍然能用到這個值。

static int j;

void fun1(void)

{

static int i = 0;

i++;

}

void fun2(void)

{

j=0;

j++;

}

int main()

{

for(k=0; k<10; k++)

{

fun1();

fun2();

}

return 0;

第二個作用:修飾函數。函數前加 static使得函數成為靜態函數。但此處“static”的含義不是指存儲方式,而是指對函數的作用域僅局限於本文件(所以又稱內部函數)。使用內部函數的好處是:不同的人編寫不同的函數時,不用擔心自己定義的函數,是否會與其它文件中的函數同名。

2 .sizeof

         sizeof是關鍵字不是函數

3. signed、unsigned關鍵字

4. float變量與“零值”進行比較

5.if else語句

         先處理正常情況,再處理異常情況。

6.循環語句風格

         在多重循環中,如果有可能,應當將最長的循環放在最內層,最短的循環放

在最外層,以減少 CPU 跨切循環層的次數。

7. void

         void不能代表一個真實的變量

         void a; //錯誤

function(void a); //錯誤

8.const

         const修飾的只讀變量必須在定義的同時初始化,編譯器通常不為普通 const只讀變量分配存儲空間,而是將它們保存在符號表中,這使得它成為一個編譯期間的值,沒有了存儲與讀內存的操作,使得它的效率也很高。

         a)修飾指針

const int *p; // p 可變,p指向的對象不可變

int const *p; // p可變,p指向的對象不可變

int*const p; //p不可變,p指向的對象可變

const int *const p; //指針 p和 p指向的對象都不可變

b)修飾函數參數

const修飾符也可以修飾函數的參數,當不希望這個參數值被函數體內意外改變時使

用。例如:

void Fun(const int i);

9.extern

         extern就相當於他們的這些區別於中國人的特性。extern可以置於變量或者函數前,以

標示變量或者函數的定義在別的文件中。

       

10.struct

         空結構體的大小就定位 1個byte。struct的成員默認情況下屬性是 public的,而class成員卻是 private的。

11.union

         union維護足夠的空間來置放多個數據成員中的“一種”,而不是為每一個數據成員配置空間,在union中所有的數據成員共用一個空間,同一時間只能儲存其中一個數據成員,所有的數據成員具有相同的起始地址。例子如下:

union StateMachine

{

char character;

int number;

char *str;

double exp;

};

一個 union只配置一個足夠大的空間以來容納最大長度的數據成員.

 

12 typedef

       

 

 

二預處理

1.#if

         #if 的一般含義是如果#if後面的常量表達式為true,則編譯它與#endif之間的代碼,否則跳過這些代碼。命令#endif 標識一個#if塊的結束。#else命令的功能有點象 C語言中的 else ,#else建立另一選擇(在#if 失敗的情況下)。#elif命令意義與 else if 相同,它形成一個 if else-if階梯狀語句,可進行多種編譯選擇。

 

2.#define

         #define會原樣替換,要搞定它其實很簡單,別吝啬括號就行了。

例子:

定義一個宏函數,求 x 的平方:

#define SQR (x) x * x

試試:假設 x 的值為10,SQR (x)被替換後變成 10*10。沒有問題。

再試試:假設 x 的值是個表達式10+1,SQR (x)被替換後變成10+1*10+1。問題

這並不是我想要得到的。怎麼辦?括號括起來不就完了?

#define SQR (x) ((x)*(x))

       

三指針和數組

         注意!!!:指針的偏移值是起始地址加上指針指向對象的size。

         1.數組名a作為左值和右值的區別

         數組名不能作為左值,對指針進行加 1操作,得到的是下一個元素的地址,而不是原有地址值直接加 1。所以,一個類型為 T的指針的移動,以 sizeof(T) 為移動單位。    main()

{

int a[5]={1,2,3,4,5};

int *ptr=(int *)(&a+1);

printf("%d,%d",*(a+1),*(ptr-1));

}

&a + 1: 取數組 a的首地址,該地址的值加上 sizeof(a) 的值,即 &a + 5*sizeof(int),也

就是下一個數組的首地址,顯然當前指針已經越過了數組的界限。(int *)(&a+1):則是把上一步計算出來的地址,強制轉換為 int * 類型,賦值給 ptr。*(a+1): a,&a的值是一樣的,但意思不一樣,a是數組首元素的首地址,也就是 a[0]的首地址,&a是數組的首地址,a+1是數組下一元素的首地址,即a[1]的首地址,&a+1是下一個數組的首地址。所以輸出 2*(ptr-1): 因為 ptr 是指向 a[5],並且 ptr是 int * 類型,所以 *(ptr-1)是指向 a[4] ,輸出 5。

 

2.數組和指針的關系

文件 1中定義如下:

char a[100];

文件 2 中聲明如下:

extern char *a;

這裡,文件1 中定義了數組a,文件2中聲明它為指針。這有什麼問題嗎?平時不是總說數組與指針相似,甚至可以通用嗎?但是,很不幸,這是錯誤的。通過上面的分析我們也能明白一些,數組就是數組,指針就是指針,它們是完全不同的兩碼事!他們之間沒有任何關系,只是經常穿著相似的衣服來迷惑你罷了。下面就來分析分析這個問題:

 

定義和聲明之間的區別,定義分配的內存,而聲明沒有。定義只能出現一次,而聲明可以出現多次。這裡extern告訴編譯器 a這個名字已經在別的文件中被定義了,下面的代碼使用的名字 a是別的文件定義的。再回顧到前面對於左值和右值的討論,我們知道如果編譯器需要某個地址(可能還需要加上偏移量)來執行某種操作的話,它就可以直接通過開鎖動作(使用“*”這把鑰匙)來讀或者寫這個地址上的內存,並不需要先去找到儲存這個地址的地方。相反,對於指針而言,必須先去找到儲存這個地址的地方,取出這個地址值然後對這個地址進行開鎖(使用“*”這把鑰匙)。如下圖:

這就是為什麼 extern char a[]與 extern char a[100]等價的原因。因為這只是聲明,不分配空間,所以編譯器無需知道這個數組有多少個元素。這兩個聲明都告訴編譯器 a是在別的文件中被定義的一個數組,a 同時代表著數組 a的首元素的首地址,也就是這塊內存的起始地址。數組內地任何元素的的地址都只需要知道這個地址就可以計算出來。

但是,當你聲明為 extern char *a時,編譯器理所當然的認為 a是一個指針變量,在 32位系統下,占 4個byte。這 4個byte裡保存了一個地址,這個地址上存的是字符類型數據。雖然在文件 1中,編譯器知道a 是一個數組,但是在文件 2中,編譯器並不知道這點。大多數編譯器是按文件分別編譯的,編譯器只按照本文件中聲明的類型來處理。所以,雖然a實際大小為 100個byte,但是在文件 2中,編譯器認為a 只占4個byte。

我們說過,編譯器會把存在指針變量中的任何數據當作地址來處理。所以,如果需要

訪問這些字符類型數據,我們必須先從指針變量 a中取出其保存的地址。如下圖:

 

顯然,按照上面的分析,我們把文件 1中定義的數組在文件2 中聲明為指針會發生錯誤。同樣的,如果在文件 1中定義為指針,而在文件中聲明為數組也會發生錯誤:

文件 1

char *p = “abcdefg”;

文件 2

extern char p[];

在文件 1 中,編譯器分配4個byte空間,並命名為 p。同時p裡保存了字符串常量“abcdefg”的首字符的首地址。這個字符串常量本身保存在內存的靜態區,其內容不可更改。在文件 2中,編譯器認為 p是一個數組,其大小為 4 個byte,數組內保存的是 char類型的數據。在文件 2中使用p 的過程如下圖:

 

3. 數組參數與指針參數

無法向函數傳遞一個數組,C語言中,當一維數組作為函數參數的時候,編譯器總是把它解析成一個指向其首元素首地址的指針。

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