• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            voip
            風的方向
            厚德致遠,博學敦行!
            posts - 52,comments - 21,trackbacks - 0

            值傳遞, 指針傳遞?

            這幾天在學習C過程中,在使用指針作為函數參數傳遞的時候出現了問題,根本不知道從何得解:源代碼如下:
                createNode(BinNode *tree,char *p)
                {
                    tree = (BinNode *) malloc(sizeof(BinNode));
                    tree->data = *p;
                }
            該代碼段的意圖是通過一個函數創建一個二叉樹的節點,然而在,調用該函數后,試圖訪問該節點結構體的成員時候,卻發生了內存訪問錯誤,到底問題出在哪兒呢?

            一直不明白指針作為函數參數傳值的機制,翻開林銳的《高質量C/C++編程指南》,找到了答案。

                [如果函數的參數是一個指針,不要指望用該指針去申請動態內存]
                
            原來問題出在C編譯器原理上:編譯器總是要為函數的每個參數制作臨時副本,指針參數tree的副本是 _tree,編譯器使 _tree = tree。如果函數體內的程序修改了_tree的內容,就導致參數tree的內容作相應的修改。這就是指針可以用作輸出參數的原因。
            即上面的函數代碼經過編譯后成為:
                createNode(BinNode *tree,char *p)
                {
                    BinNode *_tree;
                    _tree = tree;
                    _tree = (BinNode *) malloc(sizeof(BinNode));
                    _tree->data = *p;
                }
            如果沒有
                _tree = (BinNode *) malloc(sizeof(BinNode));
            這個語句,在函數體內修改了_tree的內容,將會導致參數tree的內容作相應的修改,因為它們指向相同的內存地址。而
                _tree = (BinNode *) malloc(sizeof(BinNode));
            這個句,系統重新分配內存給_tree指針,_tree指針指向了系統分配的新地址,函數體內修改的只是_tree的內容,對原tree所指的地址的內容沒有任何影響。因此,函數的參數是一個指針時,不要在函數體內部改變指針所指的地址,那樣毫無作用,需要修改的只能是指針所指向的內容。即應當把指針當作常量。

            如果非要使用函數指針來申請內存空間,那么需要使用指向指針的指針
                createNode(BinNode **tree,char *p)
                {
                    *tree = (BinNode *) malloc(sizeof(BinNode));
                }
            上面的是林銳的說法,目前來說不知道怎么去理解,不過可以有另外的方案,通過函數返回值傳遞動態內存:
                BinNode *createNode()
                {
                    BinNode *tree;
                    tree = (BinNode *) malloc(sizeof(BinNode));
                    return tree;
                }
            這個倒還說得過去,因為函數返回的是一個地址的值,該地址就是申請的內存塊首地址。但是,這個容易和另外的一個忠告相混繞
                [不要用return語句返回指向“棧內存”的指針,因為該內存在函數結束時自動消亡]

            這里區分一下靜態內存,棧內存和動態分配的內存(堆內存)的區別:
            (1) 從靜態存儲區域分配。內存在程序編譯的時候就已經分配好,這塊內存在程序的整個運行期間都存在。例如全局變量,static變量。
            (2) 在棧上創建。在執行函數時,函數內局部變量的存儲單元都可以在棧上創建,函數執行結束時這些存儲單元自動被釋放。棧內存分配運算內置于處理器的指令集中,效率很高,但是分配的內存容量有限。
            (3) 從堆上分配,亦稱動態內存分配。程序在運行的時候用malloc或new申請任意多少的內存,程序員自己負責在何時用free或delete釋放內存。動態內存的生存期由我們決定,使用非常靈活,但問題也最多。

            因此,試圖返回一個棧上分配的內存將會引發未知錯誤
                char *GetString(void)
                {
                    char p[] = "hello world";
                    return p; // 編譯器將提出警告
                }
            p是在棧上分配的內存,函數結束后將會自動釋放,p指向的內存區域內容不是"hello world",而是未知的內容。
            如果是返回靜態存儲的內存呢:
                char *GetString(void)
                {
                    char *p = "hello world";
                    return p;
                }
            這里“hello world”是常量字符串,位于靜態存儲區,它在程序生命期內恒定不變。無論什么時候調用GetString,它返回的始終是同一個“只讀”的內存塊。
             
            [參考:林銳《高質量C/C++編程指南》]

            posted on 2010-10-31 19:32 jince 閱讀(694) 評論(0)  編輯 收藏 引用
            哈哈哈哈哈哈
            精品熟女少妇AV免费久久| 亚洲国产精品婷婷久久| 久久国产香蕉一区精品| 久久久久久无码国产精品中文字幕 | 亚洲综合久久综合激情久久| 精品国产91久久久久久久a| 精品久久久久久无码不卡| 99国产欧美久久久精品蜜芽| 精品99久久aaa一级毛片| 婷婷综合久久中文字幕蜜桃三电影| 欧美精品一本久久男人的天堂| 亚洲国产香蕉人人爽成AV片久久| 韩国三级大全久久网站| 少妇久久久久久被弄到高潮| 国产精品久久亚洲不卡动漫| 久久精品国产精品亚洲精品 | 国产免费久久精品99re丫y| 97久久天天综合色天天综合色hd| 久久综合视频网站| 国产午夜精品久久久久九九电影| 中文字幕热久久久久久久| 色婷婷久久综合中文久久一本| 久久国产免费观看精品| 999久久久无码国产精品| 日日躁夜夜躁狠狠久久AV| 日批日出水久久亚洲精品tv| 91性高湖久久久久| 久久精品国产91久久麻豆自制 | 久久久这里有精品| 欧美精品丝袜久久久中文字幕| 久久精品国产69国产精品亚洲| 久久久久人妻精品一区二区三区 | 久久99这里只有精品国产| 久久精品成人免费国产片小草| 91精品国产91热久久久久福利| 久久99精品久久只有精品| 97精品依人久久久大香线蕉97| 久久精品成人欧美大片| 久久久亚洲欧洲日产国码是AV| 久久天天躁狠狠躁夜夜avapp| 国产美女亚洲精品久久久综合|