從語句 char* p="test" 說起
我相信,使用
c/c++
多年的人對下面這個字串賦值語句都不會陌生吧。
char* p = "test";
同時,我也相信,各位在使用這種語句後吃過很多苦頭也不少吧?只要你想利用指標
p來改變字串的內容,你的程式都會得到乙個讓你顏面盡失乙個記憶體非法操作。比如,下面的這些語句:
p[0] = 's';
strcpy(p, "haoel");
原因就在於,
char* p = "test";
這個宣告,宣告了乙個指標,而這個指標指向的是全域性的const記憶體區,
const
記憶體區當然不會讓你想改就改的。所以,如果你一定要寫這塊記憶體的話,那就是乙個非常嚴重的記憶體錯誤。另,之所以加粗「全域性
const
記憶體區」,是強調一下,如果你不信的話,你可以試試下面這段**,看看p1和
p2的位址是不是一樣的。
char* p1 = "anything";
char* p2 = "anything";
printf(「 p1=%x, p2=%x /n」, p1, p2);
我想這應該是乙個眾所周知的問題吧。取而代之的,應該是使用陣列來做初始化宣告。如:
char str = 「hello world」;
如果現在還有哪本書中的
c的示例採用了使用const字串初始化指標的這種方式,那麼你就可以把那本書撕了,如果這本書是
c++的書話,那麼你應該把這個作者和這個出版社告上法庭,因為你不應該容忍這種學術**。如果你的部門的開發人員還有人寫出這種**的話,如果他是
c程式設計師,我想你可以在打過他的屁股後告訴他下不為例,如果他是乙個
c++程式設計師的話,我想你可以懷疑他是否有資格做乙個
c++程式設計師了。
至於你問我為什麼要對學
c++的人那麼苛刻,那是因為學過
c++的人都知道
c++中的
const
關鍵字的有著什麼樣的權力,你也應該知道
c++對
const
有著無比的照顧和關愛,幾乎所有關於
c++的書都會提到
const
這東西。所以,如果作為乙個
c++的程式設計師來說,如果你不知道的話,那就太說不過去了。
我們知道,雙引號引起來的字串是
const
的,所以,在
c++的世界中,你應該進行如下的宣告才比較穩妥:
const char *p = "test";
這樣,當你修改這個字串的內容時,編譯器會給你乙個錯誤而導致你的程式編譯不通過,從而不會產生執行時的記憶體錯誤。
可問題是,像
c++這種對型別要求很嚴格的語言來說,為什麼它在編譯諸如
char *p="test"
程式的時候不出錯,甚至連個警告都沒有(
g++和
vc++7
)?難道這是他的乙個
bug?我想,這應該是對古老的
c的乙個向下相容。因為,在
c的世界中,這種用法太多了。 在
c++中,比如:函式的引數和異常的捕獲都存在這種問題,如下所示:(因編譯器而定,在
gcc 3.4.3
版中,下例中的異常示例不能**獲,但
vc++6
中卻可以**獲)
func( char* p) //
以這種方式呼叫函式
func(「abc」);
try catch (char* p)
這些都是c++編譯器預設了可以把const char* 轉成 char* 的罪行,無疑會對大家是乙個誤導。甚至讓人無所畏懼地走入其中,並自以為走入了正途。這樣看來,這種向下相容的c++標準,就顯得有點誤人不淺了。
不過好在,
c++標準委員會早已意識到了這一點。這個
c++的
feature
被定義為了「
deprecated feature
」,即「不被建議使用的特性」。意思就是,在將來,這種特性將被從
c++中移出,於是,你目前的這種程式將無法在新的
c++編譯器上編譯通過。對於程式的可移植性來說,我們今天所寫的**尤其要注意這些「
deprecated feature」。
據我所知,目前
c++中被列為「
deprecated feature
」如下所示(可能不準確,請大家指正)下面的這些feature都已被c++標準委員會訂為廢除featrue了。
一、
隱晦的字串的const轉換。
char *p = "test";
w_char *pw = l"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 ;
class d : public b ;
對於這種語法,子類重新暴露了父類的私有成員。這會帶來很大的安全性問題。目前而言,
這個feature
對於所有的編譯器來說應該都是可以編譯通過的(連個
warning
都沒有)。但這個
feature
也是要被廢除的。
五、
檔案中域的static宣告
static int i;
static void func()
據說,這種舊的在
c中的為了實現其作用域在本檔案中的
feature
在未來的
c++中也要被取消。
const
的例子(在網上看到的)
const int a = 1;
int *p = const_cast(&a);
*p = 2;
cout << 「value a=」<< a << endl;
cout << 「value *p=」 <<*p << endl;
cout << 「address a=」 <<&a << endl;
cout << 「address p=」 <
這段**輸出的結果如下:
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
的語義,任何想要破壞這個語義的事情都會給我們帶來未知的結果。
從語句 char p test 說起
從語句 char p test 說起 陳皓 我相信,使用 c c 多年的人對下面這個字串賦值語句都不會陌生吧。char p test 同時,我也相信,各位在使用這種語句後吃過很多苦頭也不少吧?只要你想利用指標 p來改變字串的內容,你的程式都會得到乙個讓你顏面盡失乙個記憶體非法操作。比如,下面的這些語...
從語句 char p test 說起
自打上次bcb版聚時,tr老大談起他家裡整了一台伺服器的事後,令狐也心癢想整這麼個東東,我則是把自己的一台閒置電腦弄成伺服器用。但是我們這些解決方案都不夠好 比如成本高,耗電大,穩定性差。所以我設想了一種專用解決方案 用整合主機板,最好是筆記本主機板,耗電會省一些。用筆記本專用cpu,也是為了省電。...
從辭職說起
20出頭的人是熱血青年,有夢想的人自然也是滿懷激情。願意呆在乙個地方是因為那個地方能讓我們憧景,離開乙個地方,自然也是因為那個地方我們再也沒有繼續呆下來的熱情。打 辭職了以後,不知是從哪來的一股輕鬆的感覺。當時,是由於 醫學影象 之於我是乙個非常敏感的詞眼,還有是創業的一種意念,我充滿激情地走進了公...