一次偶然的情況下我發現以下代碼竟然無法被編譯通過(如果你的編譯器,比如VC6或VC2003,允許它編譯通過,我想你首先應該換個編譯器,比如GCC或VC2005):
void foo( const char* [] ) { }
int main( void )
{
char* s[2];
foo( s );
}
簡化成更一般的形式是:
char** p1 = 0;
const char** p2 = p1;
錯誤是:invalid conversion from `char**' to `const char**'.
lostpencil更加仔細,使用C編譯器給出的是一個警告:
initialization from incompatible pointer type.
隨后hpho給出了合理的解釋,同時comp.lang.c++.moderated上的Ulrich Eckhardt也用代碼進行了說明。
用代碼來說明最直觀了:
const char* s = "abc";
int main( void )
{
char* p0 = 0;
char** p1 = &p0;
const char** p2 = p1; // 先假設這一句是合法的 ( 測試時,可以先強制類型轉化一下 )
*p2 = s;
*p0 = 'A'; // 通過p0在修改不應該被修改的s,這顯然和const相違背,其運行結果不可知。
}
看了 **的 想到的
tekyDec 29, 2005 - Show original item
看完后.明白**講的為什么char** 不能自動轉化為 const char**,(原文)但對我影響最深的是下面的話:
==================================================================
char *p="abc" 能不能編譯通過要看你使用的編譯器。鑒于大量遺留代碼的存在,大部分編譯器允許其通過,或者給個警告。當然,程序員自己必須保證絕不去修改其值。
程序員不應該在代碼中出現*p='A'這樣的語句。這是當初約定好了的:編譯器允許char *p="abc"通過,而程序員保證不去修改它。
b. *p='A'編譯時應該允許通過,因為單就這條語句而言,它完全合法。
c. 運行時*p='A'能不能通過要看實際的運行環境,包括你使用的操作系統、編譯器、編譯器選項 等等,一句話,其運行結果由不得你,且不應該由你去關心,因為這種行為本身已經違反約定了。
==================================================================
工作關系吧,用CString 和string用的太多了,很少這樣定義字符串 char *p=“abcde“了
匝一看,還不適應,:(,漸漸的回想才想起一些來(哎,還是太生疏,趕快寫下來,以后別忘了)
這樣定義的字符串char *p=“abcde“ ; char *p1=“123445667“;
正如上面提到的是不能再 *p='A',運行的時候會出錯,同樣,strcpy(p,p1)也會出錯喲,
"abcde"字符串可以看做是個常量字符串了,是不能被修改的,
但如果 char p[]=“abcde“ 這樣定義,就沒有問題,你可以修改*p='A',只要不越界就ok.
并且發現這樣兩種定義
char *p=“abcde“
char p[]=“abcde“
在運行的時候,p指向的地址也不是一樣的,可見char *p=“abcde“還是有特殊的處理 :),具體怎么處理就不知道了,高手請指教:)
隨著測試,又發現個問題,可能是個老問題了吧:
int main(int argc, char* argv[])
{
int t[10];
char p1[7]="123456";
const char *p2="1234567890123213123";
int len(0);
//*p1='C'; err
len=strlen(p1);
printf("%d\n",len);
strcpy(p1,p2); ///??????????
printf("%s\n",p1);
len=strlen(p1);
printf("%d\n",len);
return 0;
}
我定義的是7個字符數組, 但用strcpy把p2拷到p1中,p1是放不下的,但程序卻正常執行,warning ,err都沒有,運行也正常?
輸出
6
1234567890123213123
19
應該是使用內存越界了阿??怎么會正常運行呢?
難道對于內存越界的使用,運氣好才崩潰表現出來,運氣不好就正常運行??