1. 程式人生 > >C Primer Plus--結構和其他資料型別(2)

C Primer Plus--結構和其他資料型別(2)

C Primer Plus–結構和其他資料型別(2)

文章目錄

列舉型別 enumerated type

列舉是用來代表整數常量的符號,列舉型別的宣告與struct宣告類似。列舉常量都是int

型的。列舉宣告的花括號內枚舉了該型別變數可能有的值。列舉是為了增強程式的可讀性。

enum vehicle {bicycle,car,plane,train,ship};

上面說了列舉型別就是int型別的常量,那麼凡是可以使用int的地方都可以使用列舉常量。

列舉預設值

列舉列表中的預設值被指定為整數值0、1、2等等。如上面列舉宣告中:
bicyclecarplanetrainship的值依次為0 1 2 3 4

為列舉指定值

    enum levels {low = 20, medium = 50, high = 80, perfect = 100};
    enum
phones {ios, windowsPhone = 60, blackberry = 80, android}; //ios = 0; android = 81

在C中,允許對列舉型別的變數使用自增(++)或自減(–)符號,但是在C++中不允許,為了使得程式相容,應該一開就將變數宣告為int型。

enum vehicle {bicycle,car,plane,train,ship};
    enum vehicle trans;
    //在C++中要宣告為
    //int trans;
    //trans此時的值不確定,需要賦值
    for (trans = bicycle;
trans <= ship ; trans++) { printf("%d\n",trans); }

名稱空間 namespace

在C中,變數名和標記名(結構標記、聯合標記、列舉標記)不在同一個名稱空間中,因此二者可以同名,但在C++中不可以。

struct car {
        char brand[30];
        int litre;
    };
    int car = 0;
    //C中不衝突

typedef關鍵字

typedef工具是一種高階資料特性,他使您能夠為某一型別建立您自己的名字。在這個方面,它和#define相似,但是它們具有三個不同之處:

  1. #define不同,typedef給出的符號名稱僅限於對型別,而不是對值
  2. typedef的解釋由編譯器而不是前處理器執行
  3. 雖然它的的範圍有限,但在其受限範圍內,typedef#define更靈活

這裡就告訴我們typedef並不建立新的資料型別,只是建立了易於使用的標籤別名。
例:頂一個一個數據類型別名BYTE,它只佔一個位元組,可以先定義一個char變數BYTE,然後在前面加上typedef即可。

typedef unsigned cahr BYTE;

BYTE x;//定義一個x
BYTE Y[10];//定義一個數組容納十個BYTE
BYTE * z;//定義一個指向BYTE的指標

總之,#define只是由前處理器對檔案裡的字元進行替換,而typedef則新建了一種資料型別的代替。

typedef char * STRING;//STRING成了char指標的別名
STRING a,b;//宣告兩個char指標a,b

//若是用define來試一試
#define STRING char *;

STRING a , b;//這裡被前處理器替換,成了char * a , b;兩個就不都是指標了,只有a是,b成了字元。

typedef struct {
	float real;
    float imag;
} COMPLEX; //將這個struct起個別名COMPLEX

COMPLEX foo = { 1.0 ,1};//一個複數

複雜的typedef

typedef char (* FRPTC())[5];

這裡FPRTC返回的是一個指向含有5個元素的char陣列的指標。

* () []修飾符

這三者優先順序有低到高:* < () = [],而且他們與變數名的結合是從左到右的。

int foo[12][24];//一個12x24的int二維陣列
int * p;//一個指向int的指標
int ** ptr;//一個指向int的指標的指標
char * strings[5];//一個數組,共5個元素,每個元素是一個指向char的指標
int (* pointer) [5];//一個指向int[5]陣列的指標
int * bar[12][24];//一個12x24的二維陣列,每個元素是一個指向int的指標
int (* pp) [12][24];//一個指向12x24二維陣列的指標
int (* ppp[3]) [4];//一個數組,共三個元素,每個元素是一個指向int[4]陣列的指標

char * func();//一個返回值為指向char的指標的函式
char (* funcp) func1();//一個指標,該指標指向一個返回型別為char的函式
char (* funcps[3]) func2();//一個數組,共3個元素,每個元素是一個指標,指標指向一個返回值為char的函式

typedef與這三個運算子結合

typedef int array5[5];
typedef array5 * p_to_array5;
typedef p_to_array5 arrayp[10];

array5 foo;//foo是一個int[5]陣列
p_to_array5 p;//p是一個指向int[5]陣列的指標
arrayp array;//array是一個數組,共10個元素,每個元素是一個p_to_array5指標

函式與指標

指標可以指向函式。指向函式的指標儲存著函式程式碼起始處的地址。當宣告一個函式指標時,必須宣告它指向的函式型別,即指定函式的返回型別以及函式的參量型別。
void eat(char * food);聲明瞭一個形式參量為字元指標的的函式,要宣告一個指向這樣型別函式的指標,需要這樣做:
void (* pointer) (char *);

宣告一個指向特定函式型別的指標,首先宣告一個該型別的函式,然後用(* pf)形式的表示式替換函式名稱,pf就成為了可指向那種型別函式的指標了。

聲明瞭指標之後,還需對指標進行賦值,賦值給指標的函式必須擁有與指標宣告中一致的形參和返回值。

函式指標作為引數

有了函式的指標,可以利用指標來訪問函式:

  • 通過 (*pf) (引數)的方式訪問函式
  • 通過 pf (引數)的方式訪問函式
#include <stdio.h>

void toUpper(char *);
void toLower(char *);
void foo( void (*pf)(char *),char * string);
int main() {
    void (*pf) (char *);
    
    char test[] = "I love you";
    
    pf = toUpper;
    
    (* pf)(test);//1
    
    pf = toLower;
    
    pf(test);//2
    
    foo(pf,test);//foo函式呼叫
}
/*
 * foo接受一個函式指標與char指標
 */
void foo( void (*pf)(char *),char * string){
    pf(string);
    puts(string);
}