宏// const // sizeof // static // volatile 等關鍵詞的用法

來源:互聯網
上載者:User

一、宏定義:主要是一些文法問題和技巧

例如:

#define FIND(s,e) (size_t)&(((struct s*)(0))->e)//求結構體內的變數相對於結構體的位移量

#define SECONDS_PER_YEAR (360*24*60*60)UL//求一年中的秒數

#define MIN(a,b) (((a)<=(b))?(a):(b))//求最小值

#define SWAP(A,B) {A=A^B;B=A^B;A=A^B;} //注意是{ }不是( )

說明:儘可能考慮移植性,由於代碼可能在16位機,也有可能在32位機器上運行,所以採用size_t和UL都是基於移植性的考慮。

 

二、const用法:定義常量,修飾指標、函數的輸入參數和傳回值,簡單說const表示唯讀意思,本質上來說它只是在全域資料段或者棧中定義的是一個唯讀常量,不是真正位於字串常量區。Const的目的是為了產生高品質的代碼,提高代碼的可讀性,同時保護好不能被任意改變的記憶體,從而降低Bug產生的機率。

    const int a = 10;

const int b;//錯誤,常量必須初始化

    int a = 10,b = 9;

    const int *p1 = &a;//指標指向的內容唯讀,不能通過該指標去寫

    *p1 = 11;//錯誤

    int * const p2 = &a;//指標本身唯讀,指標初始化到一個對象後,將不能被修改

p2 = &b;//錯誤

const int *p3 const = &a;//指標本身和指向的內容都是唯讀

 

const char *fp1(void) //修飾傳回值,表示返回的指標指向內容唯讀

{

    char *p = "dddd";

    return p;

}

void fp1(const char *str)

{

    *str = 4; //錯誤

    const char *p = str;//p必須為const,才能接受str

}

int _tmain(int argc, _TCHAR* argv[])

{

    const char *d = fp1();

    printf("%s",d);

}

 

三、extern用法:在別的檔案中定義的變數,要想在本檔案中使用,必須先用extern聲明,例如:extern a;之後就當成在本檔案中定義的變數一樣使用。

 

四、static用法:

1.修飾變數,從生存域和訪問域兩個方面說明,無論static變數定義在函數內或外,該變數都位於資料區段中;定義於函數體外的static變數的訪問域僅僅是它所在檔案中定義的函數,其他檔案無法通過extern對其聲明後訪問。

2.修飾函數,使得函數的訪問域僅僅為其所定義的檔案可見。

3.類中變數用static修飾表示變數是類變數,類中函數用static修飾表示函數只能訪問類中的static變數,不接受this指標,稱為類函數。

例如:

//file1

void fstatic(void);

static void fstatic(void)

{

    return;

}

//file2

void fstatic(void);

Main()

{

   fstatic();//聲明仍然無法調用

}

總之,static實現了c語言的封裝性,一定程度上實現了資訊的封裝和隱藏。

 

五、sizeof用法:sizeof是一個運算子,編譯器在編譯時間就能確定其的運算結果,其運算對象可以是內部資料類型名、struct類型名、class類型名、陣列變數和其他類型的變數,只有計算對象是陣列變數時,能得出數組實際的長度,其他類型的變數作為運算對象時,都將退化為對該對象的資料類型的運算。另外,在計算struct和class等使用者自訂資料類型的大小時,需要考慮編譯器會對其做最佳化處理,根據一定的原則調整,即會自動對齊,sizeof的結果往往會大於各個元素長度的和。

例一:

    short l;//sizeof(l)==2

    char *a = "abcddd";//sizeof(a)==4

    void *s = malloc(100);//sizeof(s)==4

    char b[] = "abcddd";//sizeof(b)==7*1

    float c[20];//sizeof(c)==20*4;

例二:

struct A

{

  short a;

  short b;

  short c;

};//sizeof(A)==6

struct B

{

  int a;

  char b;

  short c;

};//sizeof(A)==8

 

struct C

{

  double a1;

  long a;

  int a2;

  char b;

 

};//sizeof(B)==24

#pragma pack(1)//使用pack指令強制編譯器不做最佳化對其,這種方式一般用於這個

struct D//結構體要直接寫入檔案或者直接用於網路收發的情況下

{

  double a1;

  long a;

  int a2;

  char b;

 

};

#pragma pack()//sizeof(B)==17

說明:例二中示範了資料對其的情況,由於CPU訪問資料的特點是一次訪問多個位元組,故如果多位元組資料的首地址是2的整數倍的話,將可以一次記憶體訪問即可取得其所對應的所有資料,所以一個最佳化要求就是變數的地址是其資料類型長度的整數倍,例如int a的a的地址要求是4的整數倍。

針對結構體,如果結構體中所有元素類型相同,作為數組處理,入struct A;否則一般都是其最常元素的整數倍,例如struct B和C。這樣處理的目的是考慮定義結構體數組的情況,例如struct B b[10];那麼這10個結構體變數如果每個長度都是8,將能保證每個變數的第一個元素都能是4的整數倍,否則將達不到這個效果,不能實現高效的記憶體訪問,故編譯器將對不符合要求的結構體自動調整資料對齊。

最後需要交代的是,class中的static變數不被分配到棧上,所以不能計入sizeof中,空類的長度是1,有虛函數的長度為4,因為包含一個指向函數表的指標。

下面分析幾個面試題:

例一:

int fp1(char var[])//傳回值為4,因為var作為參數傳遞時,已經退化為普通指標,

{//故其大小就是指標的大小,不作為數組名處理,無法計算出數組長度。

   return sizeof(var);

}

 

 

例二:

//str1是一個數組名,該數組是一個指標數組,長度為3,故sizeof(str1)為3*4

void fp1(void)

{

    char *str1[] = {"hello","mico","china"};

    for(int i=0;i < sizeof(str1)/sizeof(char *);i++)

    {

       printf("%s",str1[i]);

    }

}

 

六、volatile的用法:該詞的意思是”易變的”,用於修飾變數的一個關鍵字,表示該變數在很多地方都能被改變,會被意象不到的改變,編譯器不能對其最佳化,往往用於多任務系統或嵌入式系統中,情況一:嵌入式系統中的很多外設寄存器的值會即時改變,如:#define PTA  *(volatile unsigned char *)(0x00000001);情況二:嵌入式系統記憶體中的某些變數有可能被中斷程式修改;情況三:多任務系統中的共用變數可能隨時改變。滿足這些特點之一的變數必須要用volatile修飾,保證編譯器不能對其最佳化處理,如果被最佳化,往往程式的執行結果出錯。

例一:

int a = 10;

if(a == 10)

{

   a = 11;

}

這短代碼正常被最佳化為

a = 11; 但是,如果volatile int a;則這段代碼將不被最佳化。

例二:

//原始代碼:

int square(volatile int *ptr)

{

    return *ptr * *ptr;

}

//編譯器最佳化完的代碼:

int square(volatile int *ptr)

{

    int a = *ptr;

    int b = *ptr;

    return a*b;

}

//正確代碼:由於*ptr的值隨時可能改變,故最佳化代碼中的a和b的值可能不一樣,故計

int square(volatile int *ptr) //算的結果可能有誤

{

    int a = *ptr;

    return a*a;

}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.