我正在使用Microsoft Visual Studio环境。我遇到了一种奇怪的行为
char *src ="123";
char *des ="abc";
printf("\nThe src string is %c", src[0]);
printf("\tThe dest string is %c",dest[0]);
des[0] = src[0];
printf("\nThe src string is %c", src[0]);
printf("\tThe dest string is %c",dest[0]);
结果是:
1 a
1 a
这意味着des[0]
未被初始化。因为src指向字符串的第一个元素。我想根据规则这应该有效。
答案 0 :(得分:3)
这是未定义的行为:
des[0] = src[0];
请改为尝试:
char des[] ="abc";
答案 1 :(得分:1)
由于src和des是用字符串文字初始化的,因此它们的类型实际上应该是const char *
,而不是char *
;像这样:
const char * src ="123";
const char * des ="abc";
从未为它们中的任何一个分配内存,它们只是指向预定义的常量。因此,语句des[0] = src[0]
是未定义的行为;你试图在那里改变一个常数!
任何体面的编译器都应该警告你关于从const char *
到char *
的隐式转换......
如果使用C ++,请考虑使用std::string
代替char *
,使用std::cout
代替printf
。
答案 2 :(得分:1)
ISO / IEC 14882(编程语言 - C ++)第2.13.4节说:
字符串文字是由双引号括起的字符序列(如2.13.2中所定义),可选地以字母L开头,如“...”或“L”......“。不以L开头的字符串文字是普通的字符串文字,也称为窄字符串文字。普通的字符串文字具有类型“n const char数组”和静态存储持续时间(3.7),其中n是下面定义的字符串的大小,并使用给定的字符进行初始化。 ...
是否所有字符串文字都是不同的(即存储在非重叠对象中)是实现定义的。尝试修改字符串文字的效果是未定义。
答案 3 :(得分:1)
在C中,"123"
等字符串文字存储为char
({+ 1}}在C ++中的数组。这些数组存储在存储器中,以便在程序的生命周期内可用。尝试修改字符串文字的内容会导致未定义的行为;有时它会“工作”,有时它不会,取决于编译器和平台,所以最好将字符串文字视为不可写。
请记住,在大多数情况下,“N元素数组const char
”类型的表达式将转换为“指向T
的指针”类型的表达式,其值为第一个的位置数组中的元素。
因此,当你写
T
表达式 char *src = "123";
char *des = "abc";
和"123"
从“{3}元素"abc"
数组”转换为“指向char
”的指针, char
会指向src
中的'1'
,"123"
会指向des
中的'a'
。
同样,尝试修改字符串文字的内容会导致未定义的行为,因此当您编写
时"abc"
编译器可以自由地以任何方式处理该语句,从完全忽略它到完全按照你期望的方式处理它之间的任何事情。这意味着字符串文字或指向它们的指针不能用作des[0] = src[0];
,strcpy
,strcat
等调用的目标参数,也不能用作参数像memcpy
之类的电话。
答案 4 :(得分:0)
vinaygarg :这意味着
des[0]
未被初始化。因为src指向字符串的第一个元素。我想根据规则这应该有效。
首先你必须记住* src和* dst被定义为指针,仅此而已。
所以你必须问自己究竟什么是“123”和“abc”以及为什么它不能改变?好吧,简而言之,它存储在应用程序内存中,即read-only
。为什么?字符串必须与程序一起存储,以便在运行时可用于您的代码,理论上您应该收到编译器警告,以便将非const char*
分配给const char *
。为什么是read-only
?需要保护exe和dll的内存不被覆盖,因此必须是只读的才能阻止错误和病毒修改执行代码。
那你怎么能把这个字符串变成可修改的内存呢?
// Copying into an array.
const size_t BUFFER_SIZE = 256;
char buffer[BUFFER_SIZE];
strcpy(buffer, "abc");
strncpy(buffer, "abc", BUFFER_SIZE-1);