今天發現這樣一個問題
#include <iostream> using namespace std; int main() { char ch1[10]; strcpy_s(ch1,"123456");//編譯通過 char* p = new char[10]; strcpy_s(p,"123456");//報錯:不接受2個參數 }
改成如下所示就沒有問題:
strcpy_s(p,10,"123456");//編譯通過
為什麼會這樣呢?
先看下字符數組與字符串指針的區別:
1.由雙引號括起來的字符串常量屬於靜態存儲類型,它被存儲在內存的靜態存儲區內,所以無論字符串常量出現在程序的什麼地方,它在程序的整個運行過程中只存儲一份。
如果用字符串常量初始化字符數組,就是從靜態存儲區把整個字符串復制給數組。例如:
char a[] = "hello";
如果用字符串常量初始化字符指針,就是把字符串在靜態存儲區的地址復制給指針。例如:
char *p = "world";這兩種形式的一個重要區別是不能通過指針來修改字符串的值,但是字符數組不存在這個問題,如
語句是錯誤的:
p[0] = 'p';
而如下語句沒有問題:
a[0] = 'a';
為了避免通過指針修改字符串的錯誤,建議將字符指針聲明為const類型,如下所示:
const char *p = "world";
例如:
.int main() { char str1[40]="hello world!"; //char *str1="hello world!"; str1[4]='A'; //若str1是指針型的,編譯通過,但運行是此處會段錯誤 printf("%s\n",str1); return 0; }
2.數組和指針都可以在它們的定義中用字符串常量進行初始化,盡管看上去一樣,底層的實現機制卻不相同。
定義指針時,編譯器並不為指針所指向的對象分配空間,它只是分配指針本身的空間,除非在定義的同時賦值給指針一個字符串常量進行初始化。例如:下面的定義創建了一個字符串常量(為其分配了內存):
char *p=”abcdefg”;
注意只有對字符串常量才是如此,不能指望為浮點數之類的常量分配空間,如:
Float *p=2.34; /*錯誤,無法通過編譯*/
下面結合一個實例談談初始化指針時創建的字符串常量與數組中的字符串的區別:
如指針相反,由字符串常量初始化的數組是可以修改的。其中的單個字符在以後可以改變。
下面是一個在vc6中的一個例子,完成將一個字符串中的所有大寫字母全部轉換為小寫字母的功能:
#include<iostream> #include<ctype.h> using namespace std; /******************************************************************************/ /* * Convert a string to lower case */ int strlower(char *string) { if(string==NULL) { return -1; } while(*string) { if(isupper(*string)) *string=tolower(*string); string++; } *string='\0'; return 0; } /* char *strlower(char *string) { char *s; if(string == NULL) { return NULL; } s = string; while(*s) { if(isupper(*s)) { *s = (char) tolower(*s); } s++; } *s = '\0'; return string; } */ void main() { char *test="ABCDEFGhijklmN"; strlower(test); cout<<test<<endl; }
其中,如果采用char *test=”ABCDEFGhijklmN”;會產生運行時錯誤。Char test[]=”ABCDEFGhijklmN”則程序正常運行,原因如前所述。