當前位置:才華齋>計算機>C語言>

C語言中的重要概念有哪些

C語言 閱讀(1.81W)

學習是一個循序漸進的過程,需要同學們不斷的學習和努力。下面yjbys考試網小編為大家分享C語言中的幾個重要概念,希望能幫助大家更好的複習所學的知識。

C語言中的重要概念有哪些

  一、C語言的指標

1.指標說明

指標是包含另一變數的地址變數。

(1)int *p

p是一個指標,指向一個整形數。

(2)int *p()

p是一個函式,該函式返回一個指向整數的指標。

(3)int (*p)()

p是一個指標,該指標指向一個函式,這個函式返回一個整數。

(4)int *p[]

p是一個數組,該陣列的每一個元素是指向整數的指標C語言中的幾個重要概念C語言中的幾個重要概念。

(5)int (*p)[]

p是一個指標,該指標指向一個數組,這個陣列的每一個元素是一個整數。

(6)int *(*p)()

p是一個指標,該指標指向一個函式,這個函式返回一個指向整數的指標。

2.指標的初始化(賦地址)

(1)通過符號&取變數(包括結構變數、陣列第一個元素)的地址賦給指標;

(2)把陣列名賦給指標;

(3)把函式名賦給指向函式的指標;

(4)動態分配記憶體

例:struct c{double r,i;};

struct c *p;

p=(struct c *)malloc(sizeof(struct c));

3.指標與陣列、函式的關係

(1)對於一維陣列 int a[i] 或指標 int *a

a+i 指向 a[i]

(2)對於字串 char s[i] 或指標 char *s

s+i 指向第 i個字元 s[i]

(3)對於二維陣列int a[i][j]

*a+j 指向 a[0][j]

*(a+i) 指向 a[i][0]

*(a+i)+j 指向 a[i][j]

例:對於 a[2][3]={1,2,3,4,5,6,}; 有 *(*(a+1)+1)=5;

(4)對於字串陣列char p[i][j] 或字元型指標陣列char *p[i]

*p+j 指向第 0個字串的第 j個字元

*(p+i) 指向第 i個字串的第 0個字元

*(p+i)+j 指向第 i個字串的第 j個字元

例:對於 *p[]={"ABC","DEF"}; 有 *(*(p+1)+1)='E';

例:對於 char p[][3]={"ABC","DEF"}; 有 *(*(p+1)+1)='E';

(5)對於指標陣列int *a[i]

a[i] 指向 變數i

即 *a[i]=變數i 或 a[i]=&變數i

(6)對於結構struct XY

{int x;int *y}*p;

p是指向結構XY的指標

(*p).x 或 p->x 是表示 x 的內容

(*p).y 或 p->y 是表示指標 y 的值(地址)

*(*p).y 或 *p->y 是表示 y 所指的內容

&(*p).x 或 &p->x 是表示 x 的地址

(7)指向函式的指標

對於 void func(char *str)

{…}; //定義了一個函式

void (*p)(char*);//定義了一個函式指標

p=func; //讓指標指向函式

則(*p)("…"); //用指標p可以呼叫函式func

(8)指向多個不同函式的指標陣列

對於void function_1() {…};

void function_4() {…}; //定義了四個函式

typedef void(*menu_fcn)();//定義了指向函式的指標

menu_fcn command[4]; //定義了指標陣列

command[0]=function_1;

command[3]=function_4; //讓指標陣列指向四個函式

則command[0](); //用指標陣列中的一個元素呼叫一個函式

4.指標的分類

(1)近指標(near):

近指標為16位指標,它只含有地址的偏移量部分。近指標用於不超過64K 位元組的單個數據段或程式碼段。在微、小和中編譯模式下產生的資料指標是近指標(預設狀態);在微、小和中編譯模式下產生的碼指標(指向函式的指標)是近指標(預設狀態)。

(2)遠指標(far)

遠指標為32位指標,指標的段地址和偏移量都在指標內。可用於任意編譯模式。每次使用遠指標時都要重灌段暫存器。遠指標可定址的目標不能超過64K ,因為遠指標增減運算時,段地址不參與運算。在緊湊、大和巨模式下編譯產生的資料指標是遠指標(預設狀態)C語言中的幾個重要概念計算機考試。

(3)巨指標(huge)

巨指標為32位指標,指標的段地址和偏移量都在指標內。可用於任意編譯模式。遠指標定址的目標可以超過64K 。巨指標是規則化的指標。

5.指標的轉換

(1)遠指標轉換成巨指標

使用以下函式

void normalize(void far * * p)

{

*p=(void far *)(((long)*p&0xffff000f)+(((long)*p&0x0000fff00<<12));

}

6.指標的使用

(1)將浮點數轉換成二進位制數

float ff=16.5;

unsigned char *cc;

(float*)cc=&ff;

//此時cc的內容為"00008441"

//即cc第一個位元組=0;第二個位元組=0;第三個位元組=0x84;第四個位元組=0x41;

(2)將二進位制數轉換成浮點數

float ff;

unsigned char *cc;

cc=(unsigned char*)malloc(4);

cc=(unsigned char*)&ff;

*(cc+0)=0;

*(cc+1)=0;

*(cc+2)=0x84;

*(cc+3)=0x41;

//此時ff=16.5

free(cc);

  二、C 語言的函式

1.使用者自定義函式格式

型別 函式名(形式引數表)

引數說明

{

……

}

2.函式的呼叫方式

(1)傳值方式

①傳給被呼叫函式的是整型、長整型、浮點型或雙精度型變數。被呼叫的函式得定義相應的變數為形參。

②傳給被呼叫函式的是結構變數。被呼叫函式得定義結構變數為形參。

③傳給被呼叫函式的是結構變數的成員。被呼叫函式得定義與該成員同類的變數為形參。

(2)傳址方式

①傳給被呼叫函式的是變數的地址C語言中的幾個重要概念C語言中的幾個重要概念。被呼叫函式得定義指標變數為形參。

②傳給被呼叫函式的是陣列的地址即陣列名。被呼叫的函式得定義陣列或指標變數為形參。

③傳給被呼叫函式的是函式的地址即函式名稱。被呼叫函式得定義指向函式的指標變數為形參。

④傳給被呼叫函式的是結構的地址。被呼叫函式得定義結構指標為形參。

3.函式呼叫(傳值方式)結果的返回

(1)返回的是數值

要求被呼叫的函式型別與接收返回值的.變數型別相同。

(2)返回的是指標

要求被呼叫的函式是指標函式,其指向的型別與接收的指標變數指向型別相同。

(3)不返回任何值

被呼叫的函式是void型

  三、C 語言的資訊壓縮法

1.使用位運算子

要把 5個數據的值壓縮到一個字(16位)中,假定其中三個(f1、f2、f3)是標記(真或偽)各佔一位;第四個是叫type的整數,其取值範圍為 1到12,需要 4位的儲存器;最後一個叫作index 的整數,其取值範圍為從 0到 500,需佔 9位C語言中的幾個重要概念計算機考試。為此定義一個整型變數:unsigned int packed_data,可包含此 5個值。下圖是位域分配。

typeindex

f1f2f3┌──┐┌───────┐

┌┬┬┬┬┬┬┬┬┬┬┬┬┬┬┬┐

└┴┴┴┴┴┴┴┴┴┴┴┴┴┴┴┘

把 n的 4個低位的值置入packed_data 的type域中,用下面的語句:

packed_data=(packed_data & ~(0xf<<9))|((n&0xf)<<9);

其中位或符號|左邊是將type域置 0,右邊是取 n的低 4位後左移9 位到type域中。

從packed_data 的type域中提取數值並把它賦予 n的語句是:

n=(packed_data>>9) & 0xf;

2.使用位域結構

(1)定義一個叫做 packed_struct的結構,含有 5個成員

struct packed_struct

{

unsigned int f1:1

unsigned int f2:1;

unsigned int f3:1;

unsigned int type:4;

unsigned int index:9;

};

(注:在結構中還可以放入普通資料型別,如char c;等)

(2)定義一個變數

struct packed_struct packed_data;

(3)把packed_data 的type 域置於n的低位,用語句

packed_=n;

(4)從packed_data 中提取type域(按要求,把它移到低位),並把它賦予 n,用語句

n=packed_;

3.使用聯合

(1)一個無符號整型數與一個結構(其中包含許多無符號變數)共用一儲存區,當無符號整型數被賦值後,可通過結構變數獲得各位的值。

例如,定義一個聯合

union {

unsigned equi;

struct {

unsigned boot :1;

unsigned copr :1;

unsigned rsize:2;

unsigned vmode:2;

unsigned dnum :2;

unsigned:1;

unsigned cnum :3;

unsigned gnum :1;

unsigned:1;

unsigned pnum :2;

}beq;

}eq;

當呼叫BIOS INT 11H中斷後,將AX的值賦給,就可以從得到PC機有無系統盤的資訊;從得到PC機有無浮點運算部件的資訊。......

(2)兩個結構共享同一儲存區域

例如:union REGS

struct WORDREGS{unsigned int ax,bx,cx,dx,si,di,cflag,flags};

struct BYTEREGS{unsigned char al,ah,bl,bh,cl,ch,dl,dh};

union REGS {struct WORDREGS x;struct BYTEREGS h;}

  四 、位運算

1.數的編碼—補碼

(1).正數的補碼與原碼同。

(2).負數的補碼為

①第一位(符號位)為 1;

②剩餘原碼位數逐位取反;

③然後對整個數加 1。

2.位邏輯運算的特殊用途

(1).取一個數中的某些位元組

例a & 0x00ff得到a的低位元組,a & 0xff00得到a的高位元組。

┌─┬───┬────┬────────┐

│數│十進位制│十六進位制│補碼│

├─┼───┼────┼────────┤

│ a││0x2cac│0010110010101100│

│││0x00ff│0000000011111111│

├─┴───┼────┼────────┤

│ 按位與 │ ox00ac │0000000010101100│

│ 運算結果 │││

└─────┴────┴────────┘

(2).將一個數的某些特定位置1

例a | 0x0f使a的低4位改為1。

┌─┬───┬────┬────────┐

│數││十六進位制│補碼│

├─┼───┼────┼────────┤

│a ││0x0030│0000000000110000│

│││0x000f│0000000000001111│

├─┴───┼────┼────────┤

│按位或││0000000000111111│

│運算結果│││

└─────┴────┴────────┘

(3).將某數特定位置翻轉

例a ^ 0x000f使a的低4位翻轉(0變1;1變0)。

┌─┬───┬────┬────────┐

│數││十六進位制│補碼│

├─┼───┼────┼────────┤

│a ││ 0x007a │0000000001111010│

│││ 0x000f │0000000000001111│

├─┴───┼────┼────────┤

│ 按位異或 ││0000000001110101│

│ 運算結果 │││

└─────┴────┴────────┘

(4)將a的右起第2位反向變化(1變0,0變1)

a=a^0x02;//(0x02=00000010),異或的意義是"同值為0"

(5).將兩個數(整型數)的值互換

例a=a^b;b=b^a;a=a^b; //三步使得a、b的值互換

3.移位運算的特殊用途

(1).將某數除以2(右移1位)

例a>>2 使得a被4除

①對於 signed a=-8,a>>2

a=-8

┌─┬─┬─┬─┬─┬─┬─┬─┐

│1 │1 │1 │1 │1 │0 │0 │0 │

└─┴─┴─┴─┴─┴─┴─┴─┘

├─┬─┐──>└───┐

┌─┬─┬─┬─┬─┬─┬─┬─┐

│1 │1 │1 │1 │1 │1 │1 │0 │

└─┴─┴─┴─┴─┴─┴─┴─┘

a=-2

②對於unsigned a=248,a>>2

a=248

┌─┬─┬─┬─┬─┬─┬─┬─┐

│1 │1 │1 │1 │1 │0 │0 │0 │

└─┴─┴─┴─┴─┴─┴─┴─┘

└───┐ ──> └───┐

┌─┬─┬─┬─┬─┬─┬─┬─┐

│0 │0 │1 │1 │1 │1 │1 │0 │

└─┴─┴─┴─┴─┴─┴─┴─┘

補0──┴─┘a=62

(2).將某數乘以2(左移1位)

注左移時signed 與unsigned變數的情況一樣,均要補0。

(3)將x的右起第n(n>=0)位置0

x&=~(1《n); 若x是long,則x&=~((long)1《n);

(4)將x的右起第n(n>=0)位置1

x|=1《n;

若x是長整形數則 x|=(long)1《n;

  五、C語言訪問CPU暫存器的方法

1.使用聯合REGS,和函式 int86() / int86x() / intr()

REGS是用來在進行 DOS軟中斷呼叫時向各個暫存器傳輸資料或從各個暫存器取出返回值。

union REGS 示意圖

structstruct

WORDREGSBYTEREGS

┌ ┌───────┬──────┐──┬── ┐

│ ││ al │ 1 byte│

│ │ax├──────┤──┴─ 2 bytes

│ ││ ah │ │

│ ├───────┼──────┤───── ┘

│ ││ bl │

│ │bx├──────┤

│ ││ bh │

│ ├───────┼──────┤

│ ││ cl │

│ │cx├──────┤

│ ││ ch │

│ ├───────┼──────┤

│ ││ dl │

│ │dx├──────┤

│ ││ dh │

union regs├───────┼──────┤

│ │││

│ │si││

│ │││

│ ├───────┤│

│ │││

│ │di││

│ │││

│ ├───────┤│

│ │││

│ │cflag ││

│ │││

│ ├───────┤│

│ │││

│ │flags ││

│ │││

└ └───────┴──────┘

│x兩個結構變數h│

└──共享同一儲存域──┘

2.使用偽變數和函式geninterrupt()

Turbo C 允許使用偽變數直接訪問相應的8086暫存器。偽變數的型別有兩種。

① unsigned int : _AX、 _BX、 _CX、 _DX、 _CS、 _DS、 _SS、 _ES、 _SP、 _BP、 _DI、 _SI

② unsigned char: _AL、 _AH、 _BL、 _BH、 _CL、 _CH、 _DL、 _DH

  六、C語言使用記憶體和暫存器的方法

1.段和段暫存器

CS用來存放程式碼段的段地址;DS用來存放全域性變數和靜態變數所在段(資料段)的段地址;SS用來存放區域性變數,引數所在段(堆疊)的段地址。 此外,還有堆段,是動態分配的記憶體。

2.微模式編譯時段的使用情況

只有一個段,從底往高依此裝入程式碼,靜態變數和全域性變數,堆。從高往低裝入堆疊。

3.小模式編譯時段的使用情況

資料、堆疊和近堆共用一個段,程式碼用一個段,還有一個遠堆(用far指標存取)。

4.中模式編譯時段的使用情況

中模式有多個程式碼段,其餘與小模式一樣。函式指標用far指標。

5.緊湊模式編譯時段的使用情況

程式碼,靜態資料,堆疊,堆(只有遠堆)各有自己的段。靜態資料的總量不得超過64K

6.大模式編譯時段的使用情況

靜態資料,堆,堆疊的分配與緊湊模式一樣;程式碼段的分配與中模式一樣。資料指標和函式指標都是遠指標C語言中的幾個重要概念計算機考試。靜態資料的總量不得超過64K。

7.巨模式編譯時段的使用情況

來自不同原始檔的程式碼放在不同的段內,來自不同原始檔的靜態資料也放在不同的段內,只有堆疊是合在一起的。

8.執行庫函式分配的記憶體:

常規記憶體區

遠堆(資料段之外) 用_fmalloc()分配,得到32位指標

├─────────┤

64│堆(未使用的記憶體)│用malloc()分配,得到16位的位移地址

KB├─────────┤

數│棧(區域性變數)│

據├─────────┤

段│全域性和靜態變數│

├─────────┤

  七、用C語言寫中斷服務程式(如果中斷服務程式不牽涉到中斷鏈以及 DOS和其本身的重入問題。) ---Turbo C

1.函式型別為interrupt 的中斷服務程式定義如下:

#include

void interrupt 函式名(bp,di,si,ds,es,dx,cx,bx,ax,ip,cs,flags);

unsigned int bp,di,si,ds,es,dx,cx,bx,ax,ip,cs,flags;

2.得先保留原中斷函式地址

void interrupt (*保留函式名)( );

保留函式名=getvect(0x中斷號);

3.在main函式中用自定義的中斷服務程式替換原來的程式

setvect(0x中斷號,函式名);

4.在main函式中啟用自定義的中斷服務程式

(1)先設定要用到的暫存器的值(用偽變數),

(2)geninterrupt(0x中斷號);

若替換的是計時中斷程式,因PC機內的計時器每秒產生18.2次中斷,則每秒自動執行18.2次新的中斷程式。

5.事後得將原中斷函式地址裝回向量表中

setvect(0x中斷號,保留函式名);