C++兼容C语言的遗留问题探讨:char *p=“hello“;

在C++中,char *p="hello"; 这种写法是否正确呢?

我们测试下,如下所示代码:

	char *p1="hello";
	cout<<p1<<endl;
	cout<<(void *)p1<<endl;

编译、运行代码,结果如图:

p1输出为hello,p1的地址为0x488001,看起来这个代码没什么问题。

 

警告:

虽然代码可以执行,但是值得注意的是,此时编译器给出了一个警告 [Warning] deprecated conversion from string constant to 'char*' [-Wwrite-strings]

这个警告的大体意思是:禁止把字符串常量转换为'char *'这种类型。

 

字符串常量:

原来,char *p = "hello";这条语句,实际执行有两个过程:

  • 首先,"hello"是字符串常量,字符串常量要放在静态存储区,且其内容是不能改变的。
  • 然后,再声明字符指针p,p指向"hello"字符串所处内存空间

我们先用例子来证明,char *p = "hello"中的"hello"是字符串常量,且在静态存储区。

#include<iostream>
using namespace std;

int main() {
	char *p3="kk";	
	char *p1="hello";
	char *p2="hello";
	
	cout<<(void *)p3<<endl;
	cout<<(void *)p1<<endl;
	cout<<(void *)p2<<endl; 
}

输出地址发现,p1和p2的地址是相同的,说明他们在静态储存区内,且只有一份字符串"hello"。

而且,观察地址发现,字符串"hello"比"kk"地址大3,"kk"长度是2,其还有个字符串的结束符'\0'。

所以我们可以认为如char *p="hello"中的双引号做了3件事: 

  • 申请了空间(在常量区),存放了字符串
  • 在字符串尾加上了'\0'    
  • 返回地址给了字符指针p

总结:char *p="hello";这样做虽然不会报错,但是因为字符串常量是存放在静态存储区,所以试图对p指向的字符串进行修改操作 将造成内存违规访问。所以编译器通过警告来告诉我们最好不用这种写法。

 

C++的兼容

那编译器为啥不直接让其编译不通过,来制止这种错误,而是只警告呢?

因为C++要兼容C语言,而在C语言中,这种写法是允许的。

在C语言中并没有字符串这个类型。字符串也就是字符数组,也就是char类型的数组。与普通数组不同的,字符串必须以'\0'作为结束符。而在C语言中,类型为T的一维数组,其首地址等效于该类型的一维指针,即T*型。于是字符串,也就是字符数组,首地址就可以当做char *型使用了。事实上,在库函数以及大多数使用到字符串作为参数的函数中,其参数都是char *型的。

所以,C++选择使用警告来告诉程序员,这种写法是不正确的,以后再编译是不会通过的。

 

const char *p

正确的写法是什么呢?const char *p="hello";

cosnt char *p="hello"可以避免程序员错误的对字符串进行修改,所以在以后的写法中,我们都应使用这种写法。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值