亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? 第7章 指針和內存分配.txt

?? 我自己整理的c語言教程 來自 c語言之家
?? TXT
?? 第 1 頁 / 共 3 頁
字號:
C語言編程常見問題解答  
 

 
發表日期:2003年9月30日      已經有2414位讀者讀過此文 
 


                                 第7章  指針和內存分配

    指針為C語言編程提供了強大的支持——如果你能正確而靈活地利用指針,你就可以直接切入問題的核心,或者將程序分割成一個個片斷。一個很好地利用了指針的程序會非常高效、簡潔和精致。
    利用指針你可以將數據寫入內存中的任意位置,但是,一旦你的程序中有一個野指針("wild”pointer),即指向一個錯誤位置的指針,你的數據就危險了——存放在堆中的數據可能會被破壞,用來管理堆的數據結構也可能會被破壞,甚至操作系統的數據也可能會被修改,有時,上述三種破壞情況會同時發生。
    此后可能發生的事情取決于這樣兩點:第一,內存中的數據被破壞的程度有多大;第二,內存中的被破壞的部分還要被使用多少次。在有些情況下,一些函數(可能是內存分配函數、自定義函數或標準庫函數)將立即(也可能稍晚一點)無法正常工作。在另外一些情況下,程序可能會終止運行并報告一條出錯消息;或者程序可能會掛起;或者程序可能會陷入死循環;或者程序可能會產生錯誤的結果;或者程序看上去仍在正常運行,因為程序沒有遭到本質的破壞。
    值得注意的是,即使程序中已經發生了根本性的錯誤,程序有可能還會運行很長一段時間,然后才有明顯的失常表現;或者,在調試時,程序的運行完全正常,只有在用戶使用時,它才會失常。    
    在C語言程序中,任何野指針或越界的數組下標(out-of-bounds array subscript)都可能使系統崩潰。兩次釋放內存的操作也會導致這種結果。你可能見過一些C程序員編寫的程序中有嚴重的錯誤,現在你能知道其中的部分原因了。
    有些內存分配工具能幫助你發現內存分配中存在的問題,例如漏洞(leak,見7.21),兩次釋放一個指針,野指針,越界下標,等等。但這些工具都是不通用的,它們只能在特定的操作系統中使用,甚至只能在特定版本的編譯程序中使用。如果你找到了這樣一種工具,最好試試看能不能用,因為它能為你節省許多時間,并能提高你的軟件的質量。
    指針的算術運算是C語言(以及它的衍生體,例如C++)獨有的功能。匯編語言允許你對地址進行運算,但這種運算不涉及數據類型。大多數高級語言根本就不允許你對指針進行任何操作,你只能看一看指針指向哪里。
    C指針的算術運算類似于街道地址的運算。假設你生活在一個城市中,那里的每一個街區的所有街道都有地址。街道的一側用連續的偶數作為地址,另一側用連續的奇數作為地址。如果你想知道River Rd.街道158號北邊第5家的地址,你不會把158和5相加,去找163號;你會先將5(你要往前數5家)乘以2(每家之間的地址間距),再和158相加,去找River Rd.街道的168號。同樣,如果一個指針指向地址158(十進制數)中的一個兩字節短整型值,將該指針加3=5,結
    果將是一個指向地址168(十進制數)中的短整型值的指針(見7.7和7.8中對指針加減運算的詳細描述)。    
    街道地址的運算只能在一個特定的街區中進行,同樣,指針的算術運算也只能在一個特定的數組中進行。實際上,這并不是一種限制,因為指針的算術運算只有在一個特定的數組中進行才有意義。對指針的算術運算來說,一個數組并不必須是一個數組變量,例如函數malloc()或calloc()的返回值是一個指針,它指向一個在堆中申請到的數組。
    指針的說明看起來有些使人感到費解,請看下例:
    char *p;    
    上例中的說明表示,p是一個字符。符號“*”是指針運算符,也稱間接引用運算符。當程序間接引用一個指針時,實際上是引用指針所指向的數據。    
    在大多數計算機中,指針只有一種,但在有些計算機中,指向數據和指向函數的指針可以是不同的,或者指向字節(如char。指針和void *指針)和指向字的指針可以是不同的。這一點對sizeof運算符沒有什么影響。但是,有些C程序或程序員認為任何指針都會被存為一個int型的值,或者至少會被存為一個long型的值,這就無法保證了,尤其是在IBM PC兼容機上。

    注意:以下討論與Macintosh或UNIX程序員無關;

    最初的IBM PC兼容機使用的處理器無法有效地處理超過16位的指針(人們對這種結論仍有爭議。16位指針是偏移量,見9.3中對基地址和偏移量的討論)。盡管最初的IBM PC機最終也能使用20位指針,但頗費周折。因此,從一開始,基于IBM兼容機的各種各樣的軟件就試圖沖破這種限制。
    為了使20位指針能指向數據,你需要指示編譯程序使用正確的存儲模式,例如緊縮存儲模式。在中存儲模式下,你可以用20位指針指向函數。在大和巨存儲模式下,用20位指針既可以指向數據,也可以指向函數。在任何一種存儲模式下,你都可能需要用到far指針(見7.18和7.19)。
    基于286的系統可以沖破20位指針的限制,但實現起來有些困難。從386開始,IBM兼容機就可以使用真正的32位地址了,例如象MS-Windows和OS/2這樣一些操作系統就實現了這一點,但MS—DOS仍未實現。
    如果你的MS—DOS程序用完了基本內存,你可能需要從擴充內存或擴展內存中分配更多的內存。許多版本的編譯程序和函數庫都提供了這種技術,但彼此之間有所差別。這些技術基本上是不通用的,有些能在絕大多數MS-DOS和MS-WindowsC編譯程序中使用,有些只能在少數特定的編譯程序中使用,還有一些只能在特定的附加函數庫的支持下使用。如果你手頭有能提供這種技術的軟件,你最好看一下它的文檔,以了解更詳細的信息。

    7.1  什么是間接引用(indirection)?
    對已說明的變量來說,變量名就是對變量值的直接引用。對指向變量或內存中的任何對象的指針來說,指針就是對對象值的間接引用。如果p是一個指針,p的值就是其對象的地址;*p表示“使間接引用運算符作用于p”,*p的值就是p所指向的對象的值。
    *p是一個左值,和變量一樣,只要在*p的右邊加上賦值運算符,就可改變*p的值。如果p是一個指向常量的指針,*p就是一個不能修改的左值,即它不能被放到賦值運算符的左邊,請看下例:

例 7.1 一個間接引用的例子

#include <stdio.h>
int
main()
{
    int i;
    int  * p ;
    i = 5;
    p = & i;         / *  now  * p = = i  * /
    / *   %Pis described in FAQ VII. 28 * /
    printf("i=%d, p=%P,   * p= %d\n" , i, P,  *p); 
    * p = 6;        / *  same as i = 6  * /
    printf("i=%d, p=%P,   * p= %d\n" , i, P,  *P);
    return 0;       / *  see FAQ XVI. 4  * / }
}

   上例說明,如果p是一個指向變量i的指針,那么在i能出現的任何一個地方,你都可以用*p代替i。在上例中,使p指向i(p=&i)后,打印i或*p的結果是相同的;你甚至可以給*p賦值,其結果就象你給i賦值一樣。

    請參見:    
    7.4  什么是指針常量?

    7.2  最多可以使用幾層指針?
    對這個問題的回答與“指針的層數”所指的意思有關。如果你是指“在說明一個指針時最多可以包含幾層間接引用”,答案是“至少可以有12層”。請看下例:
int        i = 0;
int        * ip0l = &d;
int        ** ip02 = &ip01;
int        ***ip03 = &ip02;
int        **** ip04 = &dp03;
int        ***** ip05 = &ip04;
int        ****** ip06 = &ip05;
int        ******* ip07 = &ip06;
int        ******** ip08 = &ip07;
int        ********* ip09 = &ip08;
int        **********ip10 = &ip09;
int        ***********ipll = &ip10;
int        ************ ip12 = &ipll;
************ ip12 = 1;         / *  i = 1  * /

    注意:ANSIC標準要求所有的編譯程序都必須能處理至少12層間接引用,而你所使用的編譯程序可能支持更多的層數。
    如果你是指“最多可以使用多少層指針而不會使程序變得難讀”,答案是這與你的習慣有關,但顯然層數不會太多。一個包含兩層間接引用的指針(即指向指針的指針)是很常見的,但超過兩層后程序讀起來就不那么容易了,因此,除非需要,不要使用兩層以上的指針。
    如果你是指“程序運行時最多可以有幾層指針”,答案是無限層。這一點對循環鏈表來說是非常重要的,因為循環鏈表的每一個結點都指向下一個結點,而程序能一直跟住這些指針。請看下例:
    例7.2一個有無限層間接引用的循環鏈表

/ *  Would run forever if you didn't limit it to MAX  * /
# include <stdio. h> 
struct circ_list
{
    char        value[ 3 ];         /*  e.g.,"st" (incl '\0')  */
    struct circ_list    *  next;
}; 
struct circ_list   suffixes[ ] =  {
    "th" , &.suffixes[ 1 ], / *  Oth  * /
    "st" , &.suffixes[ 2 ], / *  1st  * /
    "nd" , & suffixes[ 3 ], / *  2nd  * /
    "rd" , & suffixes[ 4 ], / *  3rd  * /
    "th",  &.suffixes[ 5 ], / *  4th  * /
    "th" , &.suffixes[ 6 ], / *  5th  * /
    "th" , & suffixes[ 7 ], / *  6th  * /
    "th" , & suffixes[ 8 ], / *  7th  * /
    "th",  & suffixes[ 9 ], / *  8th  * /
    "th" , & suffixes[ 0 ], / *  9th  * / 
};
# define  MAX  20

main()
{
    int i = 0;
    struct circ_list         *p = suffixes;
    while (i <=MAX) {
        printf("%ds%\n", i, p->value);
        + +i;
        p = p->next; 
    }
}

    在上例中,結構體數組suffixes的每一個元素都包含一個表示詞尾的字符串(兩個字符加上末尾的NULL字符)和一個指向下一個元素的指針,因此它有點象一個循環鏈表;next是一個指針,它指向另一個circ_list結構體,而這個結構體中的next成員又指向另一個circ_list結構體,如此可以一直進行下去。
    上例實際上相當呆板,因為結構體數組suffixes中的元素個數是固定的,你完全可以用類似的數組去代替它,并在while循環語句中指定打印數組中的第(i%10)個元素。循環鏈表中的元素一般是可以隨意增減的,在這一點上,它比上例中的結構體數組suffixes要有趣一些。
請參見:
    7.1 什么是間接引用(indirection)?

    7.3 什么是空指針?
    有時,在程序中需要使用這樣一種指針,它并不指向任何對象,這種指針被稱為空指針。空指針的值是NULL,NULL是在<stddef.h>中定義的一個宏,它的值和任何有效指針的值都不同。NULL是一個純粹的零,它可能會被強制轉換成void*或char*類型。即NULL可能是0,0L或(void*)0等。有些程序員,尤其是C++程序員,更喜歡用0來代替NULL。
    指針的值不能是整型值,但空指針是個例外,即空指針的值可以是一個純粹的零(空指針的值并不必須是一個純粹的零,但這個值是唯一有用的值。在編譯時產生的任意一個表達式,只要它是零,就可以作為空指針的值。在程序運行時,最好不要出現一個為零的整型變量)。

   注意:空指針并不一定會被存為零,見7.10。
    警告:絕對不能間接引用一個空指針,否則,你的程序可能會得到毫無意義的結果,或者得到一個全部是零的值,或者會突然停止運行。

    請參見:
    7.4  什么時候使用空指針?
    7.10 NULL總是等于0嗎?    
    7.24 為什么不能給空指針賦值? 什么是總線錯誤、內存錯誤和內存信息轉儲?

    7.4  什么時候使用空指針?   
    空指針有以下三種用法:
    (1)用空指針終止對遞歸數據結構的間接引用。
    遞歸是指一個事物由這個事物本身來定義。請看下例:
    /*Dumb implementation;should use a loop */
    unsigned factorial(unsinged i)
    {
        if(i=0 || i==1)
        {
           return 1;
        }
        else
        {
            return i * factorial(i-1);
        }
    }

    在上例中,階乘函數factoriai()調用了它本身,因此,它是遞歸的。

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
国产精品久久久久永久免费观看 | 欧美日韩综合不卡| 亚洲人成网站在线| 色婷婷亚洲综合| 美女国产一区二区| 国产欧美日韩精品a在线观看| 日本精品裸体写真集在线观看| 午夜影院在线观看欧美| 久久午夜老司机| 欧美日韩激情一区二区| 国产风韵犹存在线视精品| 亚洲国产另类精品专区| 欧美国产日本视频| 日韩一卡二卡三卡国产欧美| 成人免费高清视频| 日韩av一区二| 一二三区精品视频| 国产欧美日本一区二区三区| 久久一二三国产| 国产精品三级电影| 久久久久久久久久久久电影 | 亚洲免费毛片网站| 一区二区免费在线播放| 图片区小说区国产精品视频| 国产精品日韩精品欧美在线| 国产精品国产三级国产| 亚洲国产精品久久久男人的天堂| 蜜桃av一区二区三区电影| 国产精品中文字幕日韩精品| 青草av.久久免费一区| 亚洲1区2区3区4区| 国产一区二区精品久久91| 蜜桃久久久久久久| 成人久久久精品乱码一区二区三区| 色久优优欧美色久优优| 日韩欧美国产一区二区在线播放| 欧美日韩一区二区三区在线看 | 国产精品综合视频| 色丁香久综合在线久综合在线观看| 欧美人狂配大交3d怪物一区| 中文字幕欧美三区| 男女男精品视频| 色女孩综合影院| 国产日韩一级二级三级| 日韩综合小视频| 日日欢夜夜爽一区| 96av麻豆蜜桃一区二区| 99精品一区二区| 久久久精品人体av艺术| 亚洲一区视频在线| 天天色天天操综合| 不卡在线视频中文字幕| 在线不卡中文字幕| 欧美精品久久天天躁| 亚洲国产精品成人综合| 男女男精品网站| 欧美三级电影在线看| 国产精品久久久久久久久免费桃花| 日韩精品一二三区| 欧美三级中文字幕| 亚洲免费资源在线播放| 成人免费高清在线| 久久久99精品久久| 亚洲日本护士毛茸茸| 亚洲高清免费一级二级三级| 成人激情开心网| 中文久久乱码一区二区| 国产成人免费在线观看不卡| 欧美r级在线观看| 中文字幕亚洲区| 亚洲大片精品永久免费| 欧洲精品一区二区三区在线观看| 欧美精品在线视频| 亚洲在线观看免费| 欧美日韩一区国产| 天天免费综合色| 91精品在线免费| 国产精品丝袜在线| 成人av在线网| 一区二区三区资源| 91精品综合久久久久久| 午夜国产精品影院在线观看| 欧美日韩国产综合一区二区| 亚洲福中文字幕伊人影院| 欧美日韩一区二区三区四区 | 精品国产乱码久久久久久免费| 亚洲国产精品国自产拍av| 国产99一区视频免费| 欧美亚洲禁片免费| 国产欧美日韩精品a在线观看| 国产精品白丝jk黑袜喷水| 国产欧美一区二区精品性色| 99久久99久久精品免费观看| 亚洲免费在线看| 9191久久久久久久久久久| 麻豆成人久久精品二区三区红| 久久在线观看免费| 99视频精品全部免费在线| 欧美精品一区男女天堂| 国产.精品.日韩.另类.中文.在线.播放| 久久精品亚洲精品国产欧美kt∨| 波多野结衣一区二区三区| 亚洲另类春色国产| 成人高清免费观看| 亚洲电影中文字幕在线观看| 日韩视频永久免费| 97久久人人超碰| 午夜久久久久久久久久一区二区| 日韩视频一区在线观看| 99久久精品免费看| 久久成人久久爱| 日韩视频一区二区| 成人福利电影精品一区二区在线观看| 亚洲精品成a人| 精品区一区二区| 日韩免费成人网| 成a人片亚洲日本久久| 无码av免费一区二区三区试看| 国产亚洲欧洲997久久综合| 在线视频你懂得一区二区三区| 狠狠色2019综合网| 欧美本精品男人aⅴ天堂| av亚洲产国偷v产偷v自拍| 美女任你摸久久| 亚洲一区电影777| 国产精品嫩草久久久久| 日韩一区国产二区欧美三区| 91亚洲精品久久久蜜桃| 亚洲精品国产第一综合99久久| 日韩视频在线观看一区二区| 91黄色在线观看| 波多野结衣中文一区| 寂寞少妇一区二区三区| 久久精品一区二区三区不卡牛牛| 欧美日韩在线三级| 日本丰满少妇一区二区三区| 丁香桃色午夜亚洲一区二区三区| 日本亚洲最大的色成网站www| 亚洲精品va在线观看| 国产精品成人一区二区艾草 | 欧美日韩国产免费一区二区| 成人国产亚洲欧美成人综合网| 激情综合色综合久久综合| 亚洲成人精品一区二区| 亚洲综合一二三区| 樱桃国产成人精品视频| 国产精品久久久久久久久搜平片| 久久色在线视频| 亚洲视频一区在线| 欧美国产欧美综合| 国产农村妇女毛片精品久久麻豆 | xf在线a精品一区二区视频网站| 欧美裸体一区二区三区| 欧美日韩五月天| 6080午夜不卡| 日韩欧美精品三级| 久久久综合视频| 亚洲国产成人自拍| 中文字幕一区二区三区乱码在线| 国产精品三级在线观看| 中文字幕在线观看一区二区| 亚洲免费大片在线观看| 亚洲日本电影在线| 性久久久久久久久久久久 | 日韩欧美电影在线| 日韩女优视频免费观看| 欧美va亚洲va在线观看蝴蝶网| 精品美女在线观看| 国产欧美1区2区3区| 亚洲免费在线观看| 婷婷开心激情综合| 韩日精品视频一区| 97超碰欧美中文字幕| 欧美日韩在线播放一区| 日韩欧美在线不卡| 中文字幕的久久| 亚洲成人动漫av| 国产精品资源站在线| 9色porny自拍视频一区二区| 欧美在线观看禁18| 精品成人一区二区| 亚洲天堂网中文字| 日本午夜精品一区二区三区电影| 狠狠色狠狠色综合日日91app| 99视频在线观看一区三区| 欧美精品在线一区二区| 国产精品免费免费| 午夜av一区二区三区| 91免费观看视频在线| 欧美色爱综合网| 久久综合国产精品| 亚洲最大的成人av| 国产精品99精品久久免费| 色婷婷亚洲婷婷| 久久久久久99久久久精品网站| 亚洲美女淫视频| 国产精品一二三四| 欧美妇女性影城| 亚洲视频一区二区在线| 国产在线视频精品一区|