亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊(cè) 查看新帖 |

Chinaunix

  平臺(tái) 論壇 博客 文庫(kù)
12下一頁(yè)
最近訪問(wèn)板塊 發(fā)新帖
查看: 8207 | 回復(fù): 18
打印 上一主題 下一主題

《Programming in C》學(xué)習(xí)筆記 [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報(bào)告]
發(fā)表于 2007-01-06 21:12 |只看該作者 |倒序?yàn)g覽
《Programming in C》學(xué)習(xí)筆記

    我花了兩個(gè)月時(shí)間精讀《Programming in C》一書, 為的是查缺補(bǔ)漏, 打好基礎(chǔ), 進(jìn)而深刻理解C語(yǔ)言. 現(xiàn)在把書上曾經(jīng)作了標(biāo)記的地方(或者寫過(guò)代碼驗(yàn)證過(guò)的細(xì)節(jié))整理成筆記.

一.        基本數(shù)據(jù)類型
a)        基本數(shù)據(jù)類型和常量

  1. 基本數(shù)據(jù)類型                常量舉例                printf 如何格式輸出
  2. ------------------------------------------------------------------------------
  3. _Bool                         0,1                          %u  %i
  4. char                          'c' 'a'                      %c
  5. unsigned char                 'c' 'a'                      %c
  6. short int                       --                         %hi  %ho  %hx
  7. unsigned short int              --                         %hi  %ho  %hx
  8. int                           10, -20, 0xff, 0777          %i  %o  %x
  9. unsigned int                  10u, 0xffu, 0777U            %u  %o  %x
  10. long                          10l
  11.                               (這個(gè)字母l還是寫成大寫L更好看),  
  12.                               10L0xffL ,  077777L          %li  %lo  %lx
  13. unsigned long                 10UL,  0xffffffUL            %lu  %lo  %lx
  14. long long                     10LL,  0xffffffLL            %lli  %llo  %llx
  15. unsigned long long            10ULL, 0xffffffULL           %llu  %llo  %llx
  16. float                         10.00f,3.14e-7f,0x10.0p20    %f  %e  %g  %a
  17. double                        10.00,3.14e-7,0x10.0p20      %f  %e  %g  %a
  18. long double                   10.00L, 3.14e-7L             %Lf  %Le  %Lg
  19. float _Complex               
  20. double _Complex      
  21. long double _Complex      
  22. _Imaginary   
復(fù)制代碼



仔細(xì)觀察, 找到規(guī)律就可以記住了:
        u表示unsigned
        i表示int
        d表示10進(jìn)制
        o表示8進(jìn)制
        l表示long
        f表示float
        e表示科學(xué)計(jì)數(shù)法
        g表示啥我不知道(general?),智能輸出浮點(diǎn)數(shù)格式

b)        字符常量
i.        轉(zhuǎn)義字符:
        \a \b \f \n \r \t \v \\ \” \’ \?
注意:
\nnn   
        nnn是八進(jìn)制數(shù), 如果不符合下面的條件,則屬于未定義行為, vc6會(huì)忽略\字符
        正則表達(dá)式: \\[0-7]{1,3}
        一個(gè)轉(zhuǎn)義字符只能表示一個(gè)8bit字節(jié)所容納的8進(jìn)制數(shù), 即 \000 -- \377
\unnnn \Unnnn
        nnnn是十六進(jìn)制數(shù)
        正則表達(dá)式: \\[Uu][0-9a-fA-F]{1,n}
        具體可以用多大的十六進(jìn)制數(shù),要看編譯器為這個(gè)字符準(zhǔn)備了多大空間(vc6不支持)
\xnn
        nn是十六進(jìn)制數(shù), 如果不符合下面的條件,則屬于未定義行為, vc6會(huì)忽略\字符
        正則表達(dá)式: \\[0-9a-fA-F]{1,2}
        一個(gè)轉(zhuǎn)義字符只能表示一個(gè)8bit字節(jié)所容納的16進(jìn)制數(shù), 即 \x00 -- \xFF

ii.        多個(gè)字符常量
不同的編譯器自己決定如何實(shí)現(xiàn),不推薦使用,比如我見(jiàn)過(guò)有人用vc寫這樣的代碼:
        long LL = 'abcd';
        printf("%c %c %c %c \n",
                ((char*)&LL)[0], ((char*)&LL)[1],
                ((char*)&LL)[2], ((char*)&LL)[3]);

iii.        寬字符常量
        寬字符類型名: wchar_t
        vc6這樣定義它: typedef unsigned short   wchar_t;
        我的GCC定義: typedef long        wchar_t;
        寬字符常量在窄字符常量前加L, 如 L’a’  L’9’

二.        符號(hào)數(shù)和無(wú)符號(hào)數(shù)類型轉(zhuǎn)換陷阱
        一般的數(shù)據(jù)類型轉(zhuǎn)換原則大家都知道, 但是一些特殊的情況是C語(yǔ)言沒(méi)有定義的.例如把一個(gè)無(wú)符號(hào)數(shù)賦值給有符號(hào)數(shù),并且超過(guò)了有符號(hào)數(shù)的范圍:
                char c = 200;                        //結(jié)果 c == -56
                int i = 0xFFFFFFFF;        //結(jié)果 i == -1
        因?yàn)檫@是未定義行為, 原則上不同的編譯器會(huì)作出不同的處理, 事實(shí)上vc6是使用”二進(jìn)制復(fù)制”來(lái)賦值的,即把200 (0xC8) 這個(gè)字節(jié)復(fù)制到字符c中; 把0xFFFFFFFF四個(gè)字節(jié)復(fù)制到整型i中.

三.        數(shù)組初始化
        int iarr[10] = { 0 };  //這樣顯示初始化第一個(gè)元素為0, 然后默認(rèn)把其他元素初始化為0
                                //總體效果: 將所有元素初始化為0
        int iarr[10] = { [5] = 5, [7] = 1}; //C語(yǔ)言可以指定數(shù)組的索引下標(biāo)進(jìn)行初始化
                                                        //注意C++中不能這么用
        
四.        變量長(zhǎng)度數(shù)組
        “變量長(zhǎng)度數(shù)組”是C99新引入的數(shù)組. 我測(cè)試發(fā)現(xiàn)VC6是不支持這個(gè)的,但是GCC支持!我寫了這樣的測(cè)試代碼,發(fā)現(xiàn)程序居然也支持作為i是負(fù)數(shù),而且在負(fù)數(shù)的情況下,GCC的內(nèi)存分配雖然怪異(0索引元素作為數(shù)組物理內(nèi)存中的最后一個(gè)元素,依次向前排列),但也是保證正確的(數(shù)組/下標(biāo)/元素地址/指針計(jì)算不是產(chǎn)生錯(cuò)誤)。

  1. #include <stdlib.h>
  2. #include <stdio.h>

  3. void fun(int i)
  4. {
  5.     char kk = 'B';
  6.     char buf[ i ];
  7.     char mm = 'E';

  8.     printf("size :: %d %x -- %x\n", sizeof(buf), (size_t)buf, (size_t)&buf[i-1]);
  9.     buf[i-1] = 'a';
  10.     printf("\t\t\t buf[i-1]:%c\t %x:%c \t %x:%c \n", buf[i-1], (size_t)&kk, kk, (size_t)&mm, mm);
  11. }

  12. int main(int argc, char * argv[], char * envp[])
  13. {
  14.     fun(2);
  15.     fun(3);
  16.     fun(4);
  17.     fun(1);
  18.     fun(0);
  19.     fun(-1);
  20.     fun(-10);
  21. }
復(fù)制代碼


        GCC安全的為負(fù)數(shù)長(zhǎng)度的數(shù)組分配了空間,保證了這種數(shù)組的安全使用, 不會(huì)影響棧上的其他變量空間。
        下面是輸出:

  1. size :: 2 bfbfec50 -- bfbfec51
  2.                          buf[i-1]:a      bfbfec7f:B      bfbfec7e:E
  3. size :: 3 bfbfec50 -- bfbfec52
  4.                          buf[i-1]:a      bfbfec7f:B      bfbfec7e:E
  5. size :: 4 bfbfec50 -- bfbfec53
  6.                          buf[i-1]:a      bfbfec7f:B      bfbfec7e:E
  7. size :: 1 bfbfec60 -- bfbfec60
  8.                          buf[i-1]:a      bfbfec7f:B      bfbfec7e:E
  9. size :: 0 bfbfec60 -- bfbfec5f
  10.                          buf[i-1]:a      bfbfec7f:B      bfbfec7e:E
  11. size :: -1 bfbfec60 -- bfbfec5e
  12.                          buf[i-1]:a      bfbfec7f:B      bfbfec7e:E
  13. size :: -10 bfbfec60 -- bfbfec55
  14.                          buf[i-1]:       bfbfec7f:B      bfbfec7e:E
復(fù)制代碼


        我估計(jì)這種不通用的東西產(chǎn)品里應(yīng)該很少用。盡量避免使用,以增強(qiáng)移植性。

        至于數(shù)組長(zhǎng)度是負(fù)數(shù)的情況,我是這么想的:
        GCC就像數(shù)學(xué)家發(fā)現(xiàn)自然數(shù)后又發(fā)現(xiàn)了負(fù)數(shù)那樣,GCC為人們實(shí)現(xiàn)了負(fù)數(shù)數(shù)組長(zhǎng)度,并告訴我們數(shù)組長(zhǎng)度也可以是負(fù)數(shù)。至于負(fù)數(shù)有什么物理意義,數(shù)學(xué)家先不管了;數(shù)組長(zhǎng)度負(fù)數(shù)有什么實(shí)際意義,Gcc就不管了,它只是保證了正確的實(shí)現(xiàn)。

五.        結(jié)構(gòu)的初始化
        結(jié)構(gòu)的初始化盡管可以這樣:


  1.         typedef struct
  2.         {
  3.                 int a;
  4.                 char buf[10];
  5.         } Recode;

  6.         Recode rr = {
  7.                 10,
  8.                 {'0','1','2','3','4'}
  9.                 };
復(fù)制代碼


        但是這樣的隱患是初始化時(shí)必須牢記結(jié)構(gòu)成員的順序, 而且不利于結(jié)構(gòu)聲明以后的修改. 如果編譯器支持,最好使用下面的形式:


  1.         Recode rr = {
  2.                 .a = 10,
  3.                 .buf = {'0','1','2','3','4'}
  4.                 };
  5.        
復(fù)制代碼


六.        0長(zhǎng)度數(shù)組

        0長(zhǎng)度數(shù)組是個(gè)奇怪的東西, 下面的代碼(兩種形式之一)是可以通過(guò)編譯的.
                char buf[];
        或者
                char buf[0];
        有什么用處呢? 大家知道數(shù)組名其實(shí)是數(shù)組所在內(nèi)存的首地址, 那么0長(zhǎng)度數(shù)組的名字,其實(shí)是在內(nèi)存某個(gè)地方中作了一個(gè)標(biāo)記, 在適合的時(shí)候?qū)⑦@個(gè)標(biāo)記后面的一段內(nèi)存作為這個(gè)數(shù)組的內(nèi)容. 貌似數(shù)組下標(biāo)溢出了,但是善于利用這點(diǎn)                可以實(shí)現(xiàn)一個(gè)”變長(zhǎng)”結(jié)構(gòu)體.

例如下面的代碼:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>

  4. static const size_t def_name_len = 31 ;
  5. typedef struct __Name
  6. {
  7.         size_t index;
  8.         size_t len;
  9.         char buf[0];
  10. } Name, *PName ;

  11. Name * createName(size_t index, const char * strname)
  12. {
  13.         size_t len;       
  14.         PName pname = NULL;
  15.        
  16.         if (strname == NULL)
  17.         {
  18.                 len = def_name_len;
  19.         }       
  20.         else
  21.         {
  22.                 len = strlen(strname);
  23.         }
  24.        
  25.         pname = (PName) malloc( sizeof(Name) + len + 1);  
  26.        
  27.         if(pname == NULL) return NULL;

  28.         pname->index = index;
  29.         pname->len = len;
  30.         pname->buf[0] = '\0';
  31.         if (strname)  strncpy(pname->buf, strname, len+1);
  32.         return pname;
  33. }

  34. void freeName(PName pname)
  35. {
  36.         if(pname == NULL) return;
  37.         free(pname);
  38.         pname = NULL;
  39. }

  40. int main()
  41. {
  42.         int i;

  43.         PName namelist[4] = {
  44.                 createName(1, "name1"),
  45.                 createName(2, "name2"),
  46.                 createName(3, "name3"),
  47.                 createName(4, "name4"),
  48.         };
  49.        
  50.         for(i=0; i<4; ++i)
  51.         {
  52.                 if(namelist[i])
  53.                         printf("index %u \t name: %s \n", namelist[i]->index, namelist[i]->buf);
  54.         }
  55.         for(i=0; i<4; ++i)
  56.         {
  57.                 freeName(namelist[i]);
  58.         }
  59.         return 0;
  60. }
復(fù)制代碼


        struct __Name有三個(gè)成員size_t index; size_t len; char buf[0]; 但是sizeof(Name)的結(jié)果是8, 為什么呢?因?yàn)樯厦嬲f(shuō)了,” 0長(zhǎng)度數(shù)組的名字,其實(shí)是在內(nèi)存某個(gè)地方中作了一個(gè)標(biāo)記”,所以不占空間, 上面代碼中的pname = (PName) malloc( sizeof(Name) + len + 1);  一行,申請(qǐng)了一個(gè)Name結(jié)構(gòu)體變量,然后這塊內(nèi)存后面緊跟了一塊長(zhǎng)len+1的內(nèi)存,所以我們就可以用buf[0..len]來(lái)訪問(wèn)這段內(nèi)存了. 圖示如下:

  1. -------------------------------------------------------------------------
  2. |  index (4byte) | len (4byte)  |<------- len+1 byte -------->|
  3. -------------------------------------------------------------------------
  4. | <----------Name-------------->|                     
  5.                                 |<-----buf[len+1] ------------|
復(fù)制代碼


        可見(jiàn), 原理用一句話來(lái)總結(jié),就是利用數(shù)組下標(biāo)”故意”溢出來(lái)訪問(wèn)數(shù)組首地址后的內(nèi)存.

再找一個(gè)實(shí)際應(yīng)用的例子:
        在MS GDIPlus 提供的類庫(kù)中,有這樣一個(gè)結(jié)構(gòu)體來(lái)表示調(diào)色板數(shù)據(jù)


  1. typedef struct {
  2.     UINT Flags;
  3.     UINT Count; //下面數(shù)組Entries的實(shí)際元素?cái)?shù)
  4.     ARGB Entries[1]; //只包含一個(gè)元素的數(shù)組,用法類似0長(zhǎng)度數(shù)組
  5. } ColorPalette;
復(fù)制代碼


        下面的代碼使用GetPalette函數(shù)得到一個(gè)ColorPalette結(jié)構(gòu)體

  1.    UINT size = image->GetPaletteSize();//ColorPalette結(jié)構(gòu)體的實(shí)際長(zhǎng)度.
  2.    printf("The size of the palette is %d bytes.\n", size);
  3.    ColorPalette* palette = (ColorPalette*)malloc(size); //一塊內(nèi)存
  4.    image->GetPalette(palette, size);
  5.    if(size > 0)
  6.    {
  7.       printf("There are %u colors in the palette.\n", palette->Count);
  8.       printf("The first five colors in the palette are as follows:\n");
  9.       for(INT j = 0; j < palette->Count; ++j)
  10.          printf("%x\n", palette->Entries[j]);
  11.    }
復(fù)制代碼


        未完待續(xù), 書上還畫了很多地方,看來(lái)明天還要繼續(xù)總結(jié)了...

編輯了很久, 排版效果還是不佳,可以看我的blog:《Programming in C》學(xué)習(xí)筆記

[ 本帖最后由 dulao5 于 2007-1-7 15:29 編輯 ]

論壇徽章:
0
2 [報(bào)告]
發(fā)表于 2007-01-06 21:18 |只看該作者
支持一下。

論壇徽章:
0
3 [報(bào)告]
發(fā)表于 2007-01-06 21:30 |只看該作者
謝謝這位版姐

論壇徽章:
0
4 [報(bào)告]
發(fā)表于 2007-01-06 21:33 |只看該作者
int iarr[10] = { [5] = 5, [7] = 1}; //C語(yǔ)言可以指定數(shù)組的索引下標(biāo)進(jìn)行初始化
=====
這是GCC對(duì)C89的擴(kuò)展,
不過(guò)C99標(biāo)準(zhǔn)支持了這一初始化方法。

0長(zhǎng)度數(shù)組
===
c89只支持長(zhǎng)度至少為1的數(shù)組。
gcc擴(kuò)展為可以支持0長(zhǎng)度的數(shù)組,
c99使用flexible array (不知道怎么翻譯),即[],里面不出現(xiàn)數(shù)字。
flexible array 的許多用法都是受到限制的,但GCC的擴(kuò)展讓限制少了很多。
詳見(jiàn):
http://gcc.gnu.org/onlinedocs/gc ... th.html#Zero-Length

論壇徽章:
0
5 [報(bào)告]
發(fā)表于 2007-01-06 21:40 |只看該作者
看了樓上的鏈接,我明白了,int y[0]和int y[]還是不同的。
這樣的代碼能運(yùn)行我還是比較驚奇,沒(méi)研究過(guò)。。。
     struct f1 {
       int x; int y[];
     } f1 = { 1, { 2, 3, 4 } };

手頭沒(méi)有g(shù)cc,有機(jī)會(huì)再研究

論壇徽章:
0
6 [報(bào)告]
發(fā)表于 2007-01-06 21:47 |只看該作者
原帖由 dulao5 于 2007-1-6 21:40 發(fā)表
看了樓上的鏈接,我明白了,int y[0]和int y[]還是不同的。
這樣的代碼能運(yùn)行我還是比較驚奇,沒(méi)研究過(guò)。。。
     struct f1 {
       int x; int y[];
     } f1 = { 1, { 2, 3, 4 } };

手頭沒(méi)有g(shù)cc,有 ...


第二個(gè)f1肯定寫錯(cuò)了,怎么能跟結(jié)構(gòu)同名……

論壇徽章:
0
7 [報(bào)告]
發(fā)表于 2007-01-06 21:51 |只看該作者
原帖由 linyue 于 2007-1-6 21:47 發(fā)表


第二個(gè)f1肯定寫錯(cuò)了,怎么能跟結(jié)構(gòu)同名……


struct inode inode;

Linux 的內(nèi)核代碼中也用到了。

論壇徽章:
0
8 [報(bào)告]
發(fā)表于 2007-01-06 22:22 |只看該作者
原帖由 dulao5 于 2007-1-6 21:30 發(fā)表
謝謝這位版姐

女的啊

論壇徽章:
0
9 [報(bào)告]
發(fā)表于 2007-01-06 22:26 |只看該作者
打擊下LZ,暫時(shí)覺(jué)得沒(méi)意思,沒(méi)啥新意

[ 本帖最后由 toiby 于 2007-1-6 22:33 編輯 ]

論壇徽章:
0
10 [報(bào)告]
發(fā)表于 2007-01-06 22:36 |只看該作者
原帖由 poize 于 2007-1-6 22:22 發(fā)表

女的啊


漂亮女老師
您需要登錄后才可以回帖 登錄 | 注冊(cè)

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號(hào)-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號(hào):11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報(bào)專區(qū)
中國(guó)互聯(lián)網(wǎng)協(xié)會(huì)會(huì)員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過(guò)ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請(qǐng)注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP