注銷

          注銷

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            112 隨筆 :: 7 文章 :: 18 評論 :: 0 Trackbacks
          從語句 char* p="test" 說起
          ?
          陳皓
          ?
          ?
          我相信,使用 C/C++ 多年的人對下面這個字符串賦值語句都不會陌生吧。
          ?
          ????????????? char* p = “anything”;
          ?
          同時,我也相信,各位在使用這種語句后吃過很多苦頭也不少吧?只要你想利用指針 p 來改變字符串的內容,你的程序都會到一個讓你顏面盡失一個內存非法操作。比如,下面的這些語句:
          ?
          ????????????? p[0] = ‘s’;
          ????????????? strcpy(p, “haoel”);
          ?
          原因就在于, char* p = “hello world”; 這個聲明,聲明了一個指針,而這個指針指向的是全局的 const 內存區 const 內存區當然不會讓你想改就改的。所以,如果你一定要寫這塊內存的話,那就是一個非常嚴重的內存錯誤。另,之所以加粗“全局 const 內存區”,是強調一下,如果你不信的話,你可以試試下面這段代碼,看看 p1 p2 的地址是不是一樣的。
          ?
          ????????????? char* p1 = “anything”;
          ????????????? char* p2 = “anything”;
          ????????????? printf(“ p1=%x, p2=%x \n”, p1, p2);
          ?
          我想這應該是一個眾所周知的問題吧。取而代之的,應該是使用數組來做聲明。如: char str[] = “hello world”; 如果現在還有哪本書中的 C 的示例采用了這種方式,那么你就可以把那本書撕了,如果這本書是 C++ 的書話,那么你應該把這個作者和這個出版社告上法庭,因為你不應該容忍這種學術騙子。如果你的部門的開發人員還有人寫出這種代碼的話,如果他是 C 程序員,我想你可以在打過他的屁股后告訴他下不為例,如果他是一個 C++ 程序員的話,我想你可以懷疑他是否有資格做一個 C++ 程序員了。
          ?
          ?????? 至于你問我為什么要對學 C++ 的人那么苛刻,那是因為學過 C++ 的人都知道 C++ 中的 const 關鍵字的有著什么樣的權力,你也應該知道 C++ const 有著無比的照顧和關愛,幾乎所有關于 C++ 的書都會提到 const 這東西。所以,如果作為一個 C++ 的程序員來說,如果你不知道的話,那就太說不過去了。
          ?
          ?????? 我們知道,雙引號引起來的字符串是 const 的,所以,在 C++ 的世界中,你應該進行如下的聲明才比較穩妥:
          ?????????????
          ????????????? const char *p = “anything”;
          ?
          這樣,當你修改這個字符串的內容時,編譯器會給你一個錯誤而導致你的程序編譯不通過,從而不會產生運行時的內存錯誤。
          ?
          ?????? 可問題是,像 C++ 這種對類型要求很嚴格的語言來說,為什么它在編譯諸如 char *p=”anything” 程序的時候不出錯,甚至連個警告都沒有( g++ vc++7 )?難道這是他的一個 bug ?我想,這應該是對古老的 C 的一個向下兼容。因為,在 C 的世界中,這種用法太多了。
          ?
          C++ 中,比如:函數的參數和異常的捕獲都存在這種問題,如下所示:(因編譯器而定,在 gcc 3.4.3 版中,下例中的異常示例不能被捕獲,但 VC++6 中卻可以被捕獲)
          ?
          ?????? func( char* p) { }?? // 以這種方式調用函數 func(“abc”);
          ??????
          ?????? try { thow “exception”; } catch (char* p) { }
          ?
          ?????? 這些東西,無疑會對大家是一個誤導。甚至讓人無所畏懼地走入其中,并自以為走入了正途。這樣看來,這種向下兼容的 C++ 標準,就顯得有點誤人不淺了
          ?
          ?????? 不過好在, C++ 標準委員會早已意識到了這一點。這個 C++ feature 被定義為了“ Deprecated Feature ”,即“不被建議使用的特性”。意思就是,在將來,這種特性將被從 C++ 中移出,于是,你目前的這種程序將無法在新的 C++ 編譯器上編譯通過。對于程序的可移植性來說,我們今天所寫的代碼尤其要注意這些“ Deprecated Feature ”。
          ?
          ?????? 據我所知,目前 C++ 中被列為“ Deprecated Feature ”如下所示(可能不準確,請大家指正)
          ?
          一、?????????? 隱晦的字符串的 const 轉換。

          char *p = “test”;
          w_char *pw = “test”;
          char p[] = “test”;
          ?????? 把一個 const 的字符串類型轉成 non-const 的。包括指針和數組。
          ?
          二、?????????? 隱晦的類型聲明。

          func() {}?? // 函數的隱晦返回類型是 int
          static num;??? // 變量的隱晦類型是 int
          ?????? 這種 feature C89 中還可以使用,但在 C99 C++ 中都被去除了。( gcc 3.4 版本對于這種聲明會給出編譯錯誤,而 VC++6.0 會認為這是合法的程序)
          ?
          三、?????????? 布爾變量的累加操作。
          bool isConn = false;
          isConn++; ???????? // 這個操作會把 isConn 變為 true
          就目前而言,幾乎所有的編譯器都認可這種操作,但這種用法也是不被建議的,終有一天會被取消。
          ?
          四、?????????? 更改父類成員的存取權限。
          ?
          class B
          {
          ??? protected:
          ??????? int i;
          };
          ?
          class D : public B
          {
          ???? public:
          ??????? int i;
          };
          ?
          ?????? 對于這種語法,一般來說,編譯器會把了類中的那個重復的變量認為成兩份。
          也就是說,父類的和子類的各是各的。這個 feature 對于所有的編譯器來說應該都是可以編譯通過的(連個 Warning 都沒有)。但這個 feature 也是要被廢除的。
          ?
          五、?????????? 文件中域的 static 聲明
          ?
          static int i;
          static void func()
          ?
          ?????? 據說,這種舊的在 C 中的為了實現其作用域在本文件中的 feature 在未來的 C++ 中也要被取消。
          ?
          ?
          文章到這里應該結束了,在結束之前,讓我再給大家共享一個有趣的關于 const 的例子(在網上看到的)
          ?
          ??? const int a = 1;
          ??? int *p = const_cast<int*>(&a);
          ??? *p = 2;
          ?
          ??? cout << “value a=”<< a << endl;
          ??? cout << “value *p=” <<*p << endl;
          ??? cout << “address a=” <<&a << endl;
          ??? cout << “address p=” <<p << endl;
          這段代碼輸出的結果如下:
          ?
          value a=1
          value *p=2
          address a=0xbff1d48c
          address p=0xbff1d48c
          ?
          地址都是一樣的,可值為什么不一樣呢?呵呵。這個問題看起來有點“學術味”過濃,不過是個好例子,可以讓你知道 C++ 的一些用法和一些原理。有以下幾個方面大家可以考慮一下:
          1) const int a = 1 是不是和宏有點像,會不會被編譯器優化了?
          2) 去修改一個 const 的值,本來應該是不對的。這可能會是向舊的 C 兼容。是否會讓編譯器產生未知行為?
          ?
          所以,這個示例也告訴我們,我們應該遵循 C++ 中的 const non-const 的語義,任何想要破壞這個語義的事情都會給我們帶來未知的結果。
          posted on 2006-11-19 10:50 注銷..... 閱讀(434) 評論(0)  編輯  收藏 所屬分類: c++
          主站蜘蛛池模板: 兖州市| 望江县| 忻城县| 加查县| 宁阳县| 四川省| 广平县| 尚志市| 郑州市| 辰溪县| 孟州市| 桑植县| 高青县| 右玉县| 合作市| 勐海县| 荆州市| 黑河市| 乐亭县| 衡山县| 灵丘县| 望城县| 丰宁| 黄山市| 柳州市| 页游| 明光市| 镇雄县| 靖州| 哈尔滨市| 日照市| 广元市| 贺州市| 陆丰市| 察隅县| 禄丰县| 夹江县| 五峰| 新和县| 邯郸县| 定西市|