• <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>

            Mike's blog

              C++博客 :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
              0 Posts :: 23 Stories :: 83 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(17)

            我參與的團(tuán)隊

            搜索

            •  

            最新評論

            先看一個例子:
             1#include <stdio.h>
             2#include <stdlib.h>
             3#include <string.h>
             4
             5char* fun(const char* src)
             6{
             7  static char dest[32= "";
             8  
             9  strcpy(dest, src);
            10
            11  return dest;
            12}

            13
            14int main()
            15{
            16  char s1[32= "";
            17  char s2[32= "";
            18
            19  strcpy(s1, fun("hello"));
            20  strcpy(s2, fun("world"));
            21
            22  printf("%s %s\n", s1, s2);
            23  printf("%s %s\n", fun("hello"), fun("world"));
            24
            25  return 0;
            26}

                讀一下這個程序,先看這個程序?qū)懙挠袉栴}沒(假設(shè)fun函數(shù)的參數(shù)長度小于32)?如果你對這個程序中的fun函數(shù)返回一個局部變量的數(shù)組產(chǎn)生了疑問,那么我希望你是沒注意到我使用的static類型,若你仍有疑問,建議你先回去查查static變量的作用域和生命周期的概念。
                OK,是運(yùn)行這個程序的時候了,看一下運(yùn)行結(jié)果是否跟你想象的一樣呢?如果是一樣的,那么這篇文章你不用看了,因為你已經(jīng)掌握了我下面要說的問題了。好吧,對于不理解運(yùn)行結(jié)果的朋友,我們來分析一些下面那個printf語句,首先要知道printf中的表達(dá)式、函數(shù)的執(zhí)行順序是至右向左的,也就是先執(zhí)行了fun("world")返回了dest的地址,然后再執(zhí)行fun("hello")也返回了dest的地址,而這兩次返回的dest用的同一塊地址(因為是static類型),也就是第二次的執(zhí)行覆蓋了第一次執(zhí)行的結(jié)果,對dest地址進(jìn)行了重新的賦值,所以結(jié)果就是打印兩個hello了。


                我們在寫C/C++程序的時候,經(jīng)常需要從調(diào)用函數(shù)中取得自己想要的數(shù)據(jù),這就需要調(diào)用者和函數(shù)之間要有個內(nèi)存的交互,我們通常采用的方法是傳遞一個指針給被調(diào)函數(shù),作為被調(diào)函數(shù)的輸出參數(shù),這也是我們常用的、規(guī)范的做法。
                但有很多程序員比較習(xí)慣直接取返回值,這就面臨一個問題就是普通局部變量都是在棧上分派的,會隨著函數(shù)的結(jié)束而彈棧釋放,那么就會出現(xiàn)返回局部變量數(shù)組的問題,這時有人會想到用malloc或new在堆上分派內(nèi)存,沒錯,這樣是避免了前面說的問題,但這樣又會帶來新的問題,就是需要在外部對這塊內(nèi)存進(jìn)行釋放,這個是比較難把握的,多次釋放會出現(xiàn)程序的crash,忘記釋放了會出現(xiàn)內(nèi)存leak,所以這種方法也不被推薦。還有人想到了更另類的方法,就是上面例子中的static類型,沒錯,static變量也是全局的,但就會出現(xiàn)上面程序的運(yùn)行結(jié)果(可以認(rèn)為不是我們想要的結(jié)果,也就是錯誤的結(jié)果)。
                所以,我們要慎用返回函數(shù)內(nèi)部的static內(nèi)存的這種設(shè)計,但如果在無法改變設(shè)計模式的情況下(有些系統(tǒng)函數(shù)的實(shí)現(xiàn),比如inet_ntoa,可以通過在man手冊中看到這樣的一句話:The string is returned in a statically allocated buffer, which subsequent calls will overwrite),那么在自己使用的時候一定要注意,不要試圖保存返回的內(nèi)存地址或引用,而要保存返回內(nèi)存的內(nèi)容,也就是例子程序中的strcpy兩行。

            inet_ntoa的錯誤使用(判斷兩個IP地址是否相等):

             1struct in_addr addr1;
             2struct in_addr addr2;
             3
             4// 網(wǎng)絡(luò)包中包含了源地址
             5addr1.s_addr = 0x6500A8C0 // 192.168.0.101
             6addr2.s_addr = 0x6600A8C0 // 192.168.0.102
             7
             8// 這個if語句將永遠(yuǎn)為真
             9if (strcmp(inet_ntoa(addr1), inet_ntoa(addr2)) == 0{
            10  // do something
            11}
             else {
            12  // do other thing
            13}
            posted on 2008-11-25 15:06 老狼 閱讀(749) 評論(2)  編輯 收藏 引用 所屬分類: C/C++

            Feedback

            # re: 返回static內(nèi)部變量的陷阱[未登錄] 2008-11-27 15:05 小兵
            學(xué)習(xí)了  回復(fù)  更多評論
              

            # re: 返回static內(nèi)部變量的陷阱 2009-01-07 12:18 July
            很好的文章,謝謝分享  回復(fù)  更多評論
              

            97超级碰碰碰碰久久久久| 国产—久久香蕉国产线看观看| 久久91这里精品国产2020| 国产精品免费久久久久久久久| 国产三级精品久久| 中文字幕热久久久久久久| 久久香蕉国产线看观看精品yw| 久久综合中文字幕| 99久久免费国产精品特黄| 国产精品99精品久久免费| 久久久久久久综合日本| 久久亚洲私人国产精品vA| 久久国产三级无码一区二区| 久久久久国产精品人妻| 国产精品久久久久久久午夜片| 2021国产精品久久精品| 久久综合九色综合欧美狠狠| 无码人妻精品一区二区三区久久| 一本久久a久久精品综合夜夜| 久久精品成人欧美大片| 久久久久久久国产免费看| 青草影院天堂男人久久| 久久天天躁狠狠躁夜夜躁2O2O| 青青草国产97免久久费观看| 久久免费视频观看| 国产精品99久久精品| 东方aⅴ免费观看久久av| 午夜精品久久久久成人| 久久久久人妻一区精品| 亚洲综合婷婷久久| 国产精品无码久久综合网| 狠狠色婷婷综合天天久久丁香| 久久久久久国产精品无码超碰| 久久人人爽人人爽人人爽| 久久性生大片免费观看性| 久久久精品国产Sm最大网站| 2020最新久久久视精品爱| 欧美精品一本久久男人的天堂| 日本一区精品久久久久影院| 久久亚洲高清观看| 久久久久亚洲精品无码网址|