從語句 char p test 說起

2021-04-12 13:14:17 字數 4484 閱讀 3769

從語句 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來改變字串的內容,你的程式都會得到乙個讓你顏面盡失乙個記憶體非法操作。比如,下面的這些語句 p...

從語句 char p test 說起

自打上次bcb版聚時,tr老大談起他家裡整了一台伺服器的事後,令狐也心癢想整這麼個東東,我則是把自己的一台閒置電腦弄成伺服器用。但是我們這些解決方案都不夠好 比如成本高,耗電大,穩定性差。所以我設想了一種專用解決方案 用整合主機板,最好是筆記本主機板,耗電會省一些。用筆記本專用cpu,也是為了省電。...

從辭職說起

20出頭的人是熱血青年,有夢想的人自然也是滿懷激情。願意呆在乙個地方是因為那個地方能讓我們憧景,離開乙個地方,自然也是因為那個地方我們再也沒有繼續呆下來的熱情。打 辭職了以後,不知是從哪來的一股輕鬆的感覺。當時,是由於 醫學影象 之於我是乙個非常敏感的詞眼,還有是創業的一種意念,我充滿激情地走進了公...