我的程序出现了这种奇怪的行为,我无法弄清楚。我的教授向我展示了我的程序中的一个缺陷,当我构造一个对象时,我只是复制一个 char 指针,而不是创建整个数组的新副本,这样你就可以随意使用它。他用类似的代码演示了这一点。
代码:
char sweat[] ="Sweater";
warenkorb = new WareImKorb(new Textil (205366,4.2,sweat,40),2,warenkorb);
sweat[0] = '\0';
现在如果我成功了:
char* sweat ="Sweater";
程序运行良好,直到我尝试汗 [0] = ' '; 然后它就崩溃了。
但是这有效: char cc[] ="毛衣"; 炭*汗水=抄送;
这真的让我很烦恼,我不明白为什么版本 1 不起作用。 希望你们能帮助我,否则我会疯狂地思考这个问题。
“Sweater”是一个字符串文字,可能驻留在只读存储器中。使用 char[] 语法将此文字复制到 char 数组中,使用 char * 语法(实际上应该是 const char *)仅指向原始字符串文字。
char* sweat ="Sweater";
sweat[0] = '\0'
这里
sweat
指向一个CONSTANT数据。 “Sweater”是 const 文字数据,驻留在只读存储器中的某个位置,并且 sweat
本身指向此数据。 它不会复制它。因此,当您执行sweat[0]='\0'
时,它会尝试更改 CONSTANT 数据的第一个字符。因此出现了错误。顺便说一句,如果你在声明中没有写 const
,那么一个好的编译器应该发出警告,如 const char* sweater = "Sweater"
。请参阅此处的警告:http://www.ideone.com/P47vv
但是当你写
char sweat[] = "Sweater"
时,会创建一个 char 数组,从 CONSTANT 数据中复制数据,即 "Sweater"
;该数组的元素本身是可以修改的!
让我们看到一个有趣的事情:因为在第一种情况下,它不会复制 const 数据,所以无论你声明多少个变量(都指向相同的数据),所有变量的地址都是相同的。看看这个:
#include<cstdio>
int main() {
char* sweat ="Sweater"; //notice the warning
const char* another ="Sweater"; //no warning!
std::printf("%p\n", sweat); //print the address
std::printf("%p\n", another); //print the address
return 0;
}
输出:
0x8048610
0x8048610
意味着,两个 printfs 打印相同的地址!
在这里看到自己:http://www.ideone.com/VcyM6
ASCII 艺术来救援!
char sweat[]
版本在记忆中是这样的:
+---+---+---+---+---+---+---+---+
sweat: |'S'|'w'|'e'|'a'|'t'|'e'|'r'| 0 | char[8]
+---+---+---+---+---+---+---+---+
而
char* sweat
版本看起来像这样:
+---+---+---+---+---+---+---+---+
|'S'|'w'|'e'|'a'|'t'|'e'|'r'| 0 | const char[8]
+---+---+---+---+---+---+---+---+
^
|
|
+-|-+
sweat: | | | char*
+---+
没错,一个
char*
指向一个const char
。事实上,您可以将字符串文字分配给非常量字符指针,这在 C++ 的静态类型系统中是一个令人讨厌的神圣现象。诅咒你,向后兼容!
C++ 不是托管语言。避免创建指向大小不正确的字符数组的指针。以下两个示例都是更好的解决方案:
char* sweater = new char[10];
sweater[0] = '\0';
delete [] sweater;
sweater = NULL;
或者更好:
std::string sweater = "";
在不起作用的版本中,您没有创建任何字符数组。你只是在玩指针。
要使
sweat[0] = '\0'
成为有效的语句,您需要 sweat
成为实际的字符数组。
这只能通过
char sweat[] = "XXXX";
或 char sweat[20];
完成