第二天

1.C語言的存儲類型有這四種:auto,register,,extern和static類型,其中,在缺省的情況下,編譯器默認的所有變量都是auto的。而regeister寄存器則是最快的,但是由於其數量很少,所以彌足珍貴。extern是申明外部變量和函數的。static比較複雜,也比較重要,會專門講解。這裏爲了測試register和auto的效率,我們做了一下實驗。

#include <stdio.h>

int main()

{

   register int i = 0,j = 0;

   //int i = 0,j = 0;

       for(i = 0;i < 10000;i++)

   {

       for(j = 0;j < 100000;j++)

       {

           ;

       }

   }

return 0;

}

在運行的時候,我們用time a.out命令簡單測試一下程序的執行時間,當使用int i = 0,j = 0;語句的時候,打印有:

程序大約執行了2.2秒,而使用register int i=0,j=0的時候,打印有:

執行的時間約爲0.6秒,比上面快了近4倍,所以register的速度比較快,因爲變量存在寄存器中。

2.對於關鍵字,大家要記住,sizeof是一個關鍵字,不是函數。

3.在C99標準中,拓展了C語言的類型,增加了bool類型。我們在C89標準中如果要使用bool類型,則需要使用<stdbool.h>頭文件,見下面實例:

#include <stdio.h>

#include <stdbool.h>

int main()

{

   bool a = 0.001;

   printf("true = %d\n",true);

printf("false = %d\n",false);

printf("a = %d\n",a);

return 0;

}

打印的結果是:

bool a = 0.001,非零爲真,所以true = 1,false = 0,此時的a = 1表示a爲真。與a原來的值無關,大家可以把a的值改爲7.8試試!

4.關於static大家要注意這幾點:

a.static修飾變量。在修飾全局變量的時候,作用於限定於被定義的文件中,使用extern也不能訪問;在修飾局部變量的時候,在函數體中定義,只能用於該函數,即使使用該函數結束,靜態變量也不會被銷燬,下次可以繼續使用,即縮小了訪問範圍但是延長了訪問時間。

b.修飾函數的時候,函數的作用於僅限於本文件,故也叫內部函數,和修飾全局變量類似。這就是爲什麼linux內核中所有的函數和全局變量都聲明爲static的原因,linux內核代碼很多,有幾萬個文件,爲了防止文件中的函數重名造成衝突,所以就乾脆聲明爲靜態的。

c.Static修飾的靜態變量,一次定義多次使用,值具有繼承性(可以被修改),靜態區BSS段中,初始值爲0,修飾全局變量也一樣,未初始化時,初始值爲0;爲在棧區,即局部變量中,未初始化的變量,初始值全部都是隨機的髒數據。

見下面的實例:

#include <stdio.h>

//int a;

void test()

{

  // static int a = 30;

  static int a;

   printf("a = %d\n",a);

   printf("%s : &a = %p\n",__FUNCTION__,&a);

   a = a + 1;

}

void test1()

{

   int b;

   printf("b = %d\n",b);

   printf("%s : &b = %p\n",__FUNCTION__,&b);

   b = b + 1;

}

int main()

{

   int i = 0;

   for(i = 0;i < 4;i++)

   {

       test();

   }

   getchar();

   for(i = 0;i < 4;i++)

   {

       test1();

   }

   return 0;      

}

打印結果爲:

可以看到a雖然沒有初始化,但是被賦值爲0了,因爲聲明成了static,回車後,打印:

在函數test1()中,我們沒有把b聲明爲static,則b的初始值爲一個隨機值。

當我們把a的初始值設爲static int a = 30時,則打印:

說明對於staic int a = 30這條語句執行了四次,但是賦值卻只是執行了一次,就是上面所說的“一次賦值,多次使用”。

5.在linux系統編程,我們經常要使用sizeof和strlen,但是大家對它們的認識有多少呢?看看下面的例子,你知道打印出什麼嗎?

# include <head.h>

int main(int argc, const char *argv[])

{

char *p = "abcdef";

char q[9] = "1234567";

strcpy(p,"ABCDEF");

strcpy(q,"9876543");

puts(p);

printf("sizeof(p)=%d, strlen(p)=%d\n",sizeof(p),strlen(p));

printf("sizeof(q)=%d, strlen(q)=%d\n",sizeof(q),strlen(q));

return 0;

}

我們會發現,在編譯和鏈接的時候,沒有什麼錯誤,但是在執行的時候,出現了段錯誤;在VC++下運行的時候出現非法訪問的錯誤報告,段錯誤和非法訪問一般是因爲我們訪問了一段不屬於我們的內存空間。爲什麼會出現這種情況呢?

大家看看這兩條語句:char *p =“abcdef”;char q[9] =“1234567”;對於char q[9] =“1234567”;我們知道這是一個數組的普通的初始化,所以對數組再次賦值,不會出錯;但是對於char *p =“abcdef”;實際上,字符常量存在只讀數據段.rodata區,因爲是隻讀區,所以再次賦值修改肯定會報錯。當我們把strcpy(p,”ABCDEF”);註釋掉就行了,結果打印:

因爲是隻讀的,所以我們可以使用puts();打印結果,p是一個指針變量,所以只佔4個字節;strlen()求的是數組中實際存放的字符數,不包含後面的’\0’,sizeof()則求的是整個申請數組的長度(包括未用的和’\0’),所以,有了上面的結果。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章