文中参考并引用了的地址:
1.为什么const char * 的内容是可以更改的?-CSDN论坛
2.cout输出char *类型指针地址_foroverontheroad的博客-CSDN博客
回顾C的知识的时候发现C是没有严格意义上的字符串类型的,使用一个(char*)指针指向首字符的地址来实现字符串的定义和读取。
然后发现使用的时候const char*都是带const,很少见(几乎见不到)char*,所以提出了疑问,这里的const使该指针成为了常量指针,与不加const有什么影响吗?
先说结论,在有的编译器里没有影响,编译器会提示有问题(Conversion from string literal to 'char *' is deprecated),但是两者使用没有区别,因为后面定义的字符串必定是常量,也就是说不可更改值的。
但是为什么const char*定义字符串后还可以更改字符串呢?
先说结论,字符串并没有被更改,而是指针指向的地址改变了,重新申请了一块内存存储新的字符串,结论来自参考CSDN社区:为什么const char * 的内容是可以更改的?
但是很想知道发生了什么,所以做了如下实验:
#include <iostream>
using namespace std;
int main()
{
const char *a = "abcde";
cout<<"a = \t"<<a<<endl;
cout<<"*a = \t"<<*a<<endl;
cout<<"&(*a) = \t"<<&(*a)<<endl;
return 0;
}
输出结果如下:
按道理说,a是一个指针,a输出的是a指向的地址,然后*a是a指向的地址的值,但是由于这里比较特别,a是char*,输出a不会输出地址,哪怕&(*a)和&(*a[0])都不会输出地址,而是字符串。想要知道a指向的地址只能对强制转换a的类型,如int*,方法来源于这篇博客cout输出char *类型指针地址
下面的测试思路是,改变字符串内容,看是什么被改变了,然后在改变后尝试着通过记录原字符串的地址去得到原来的字符串。这里借用了一个int指针暂存原字符串的首地址。
#include <iostream>
using namespace std;
int main()
{
const char *a = "abcde";
cout<<"a = \t"<<a<<endl;
cout<<"更改前a所在的地址 = \t"<<&a<<endl;
cout<<"更改前a指向的地址 = \t"<<(int*)a<<endl;
int* temp = (int*)a; //利用一个int指针暂时存储字符串首地址
cout<<"---------------------------";
a = "fgh";
cout<<"\na = \t"<<a<<endl;
cout<<"更改前a所在的地址 = \t"<<&a<<endl;
cout<<"更改后a指向的地址 = \t"<<(int*)a<<endl;
cout<<"---------------------------";
cout<<"\n更改后收寻原字符串的数据\n";
char* p = (char*)temp; //利用字符串首地址找回原始字符串数据
for(int i=0; i<5; i++)
{
cout<<*p;
p++;
}
cout<<endl;
return 0;
}
输出结果:
可以看到,实际就是a指向的地址变了,原地址的值是没有发生更改的,之后还利用指针找到了原来的值。
const char *a,a是常量指针,指针的指向可以改变,指针指向的值不能改变,并没有违背这个规则。如果这里使用char* const a(const char* const a),本来作为字符串就是一个常量,这下又是指针常量,指针的指向也不可以更改了,那么,a算是锁死了,啥也变不了了。
无论const char *a还是char *a,都是一个常量指针,所以a[1] = 'x'是错误的,因为值不可改变,但是作为整个字符串的指针可以指向另一个地址即可。
10月30日补充
c++的STL库是有字符串string的模板的。使用string是可以替代c中的字符串的。但是两者是不同的。
1. string字符串可读可改,并不是常量,char*字符串如上所说,只读不能更改。
2. string字符串可以由char*字符串构造或者赋值,生成的string字符串同样可读可改。
#include <iostream>
using namespace std;
void test01()
{
string str1 = "hello world";
const char* temp = "hello world";
string str2 = temp;
//字符修改
str1[0] = 'x';
// temp[0] = 'x'; //非法,temp是字符串常量
str2[0] = 'x';
cout << str1 << endl;
cout << str2 << endl;
}
int main() {
test01();
return 0;
}
str1和str2都可更改,但是temp不能更改,哪怕是char* temp = "hello world";没有加const依旧是常量,不能更改的。