这是我的第一个问题。
我有一段代码:
char* str1 = "yes" ;
char* str2 = "no" ;
*str1 = *str2; //----crash
*str1 = *str2; //here program crashes.
当我可以使用整数指针执行相同操作时,为什么不使用char指针。 请解释一下。
答案 0 :(得分:4)
此原始代码,
char* str1 = "yes" ;
char* str2 = "no" ;
*str1 = *str2; //----crash
*str1 = *str2; //here program crashes.
... 无效,不允许,从C ++ 11及更高版本开始。我们现在在C ++ 14,很快就会在C ++ 17上。
C ++ 11编译器对此有何评论?例如,具有选项-std=c++14
的MinGW g ++ 5.1.0,对它说什么?
C:\my\forums\so\121> g++ foo.cpp foo.cpp: In function 'int main()': foo.cpp:3:18: error: ISO C++ forbids converting a string constant to 'char*' [-Wpedantic] char* str1 = "yes" ; ^ foo.cpp:4:18: error: ISO C++ forbids converting a string constant to 'char*' [-Wpedantic] char* str2 = "no" ; ^ C:\my\forums\so\121> _
但是,Visual C ++ 2015 update 2错误地接受了代码。
从语言中删除隐式转换为char*
的原因恰恰是它不安全。它允许代码尝试修改文字,就像这段代码一样。但是文字可以存储在只读存储器中,然后可能导致崩溃(就像它对OP所做的那样)或其他不良行为。它只是未定义的行为,任何事情都可能发生,包括代码似乎“正常工作”。
如何解决?
使用 std::string
。
像这样:
#include <string>
using namespace std;
auto main() -> int
{
string str1 = "yes" ;
string str2 = "no" ;
str1 = str2; // OK.
}
如果你绝对想要使用通过指针处理的C级零终止字符串,也许是为了与某些C代码兼容,那么根据指针使用const
,使用本地或动态分配的数组进行存储在适当的情况下,使用C标准库的字符串函数,或使用自己的函数,它们是非常简单的函数:
#include <assert.h>
#include <string.h> // The ".h" header is a C++ version of C's header.
auto main() -> int
{
char str1[] = "yes" ;
char const* const str2 = "no" ;
int const n2 = strlen( str2 );
assert( sizeof( str1 ) > n2 );
strcpy( str1, str2 );
assert( strcmp( str1, "no" ) == 0 );
}
答案 1 :(得分:1)
请注意,char*
是指向char
的指针,而不是字符串对象。文字"yes"
实际上是const char*
,因为文字将是程序数据部分中的常量数据。为了与C C ++兼容,仍允许使用char
初始化const char*
*。
另请注意,指针上的一元*
运算符会取消引用指针。
现在,您在此处将str2
('n'
)的第一个字符分配给str1
的第一个字符。由于str1
的第一个字符在程序数据部分中是常量,因此当然会失败。
如果你真的想要分配第一个char
,首先在堆上产生一个char
数组:
char* str1 = (char*)malloc(4); // here str1 is non const
strncpy(str1, "yes", 4);
const char* str2 = "no";
*str1 = *str2; // now str1 contains "nes".
我假设您正在尝试使用字符串。请更喜欢std::string
:
std::string str1 = std::string("yes");
std::string str2 = std::string("no");
str1 = str2 // now str1 is "no" as well.
使用C ++ 14字符串文字,你可以使它更优雅:
auto str1 = "yes"s;
auto str2 = "no"s;
str1 = str2 // now str1 is "no" as well.
只要合理,使用标准库而不是C遗留构造。你可能不会更好。
答案 2 :(得分:0)
根据评论,OP只想将str1
设为"no"
而不是
*str1 = *str2;
你应该做
str1 = str2;
str1
是一个指向给定字符串的第一个字符的指针。
*str
取消引用指针,为您提供字符串str1
的第一个字符。因此,您的代码正在尝试将str1
的第一个字符设置为str2
的第一个字符
在我的代码中,我将str1
指向同一位置ass str2
,这实际上会为您提供指向同一内存位置的两个变量。
如果要将str2的内容复制到str1,请使用strcpy
函数。