浅谈C++字符数组与字符串指针

C++字符串字面值常量使用双引号括起的字符序列,以’\0’为结束符。它存放在内存的常量区,自己有固定的首地址。如果将字符串字面值常量的首地址看作指针,那么这个指针是常指针常量(既是常指针,又是指针常量),即字符串指针本身只读而且其指向的内容(字符串的内容)只读。

C++处理字符串有两种方式,即:指针方式和数组方式(字符串指针和字符数组)。

数组方式是在声明数组的时候用字符串来初始化,如:

char str_arr[] = "What a nice day!";

指针方式是用字符串常量来初始化一个字符指针,如:

const char*str_pt = "What a nice day!";


先分析字符数组:

字符数组本身是可写的,也就是说在完成初始化后,可以对其进行再次赋值。同样的,也可以不对它进行初始化,而是先声明后赋值。

在C++编译器下:

cout<<str_arr<<endl; 
cin>>str_arr;

这样的语句都是合法的,前者直接输出字符串内容;后者对字符数组进行二次赋值,原值被覆盖。但是不能直接用字符串字面值常量对字符数组名赋值,也不能用字符串指针或字符数组名对字符数组名赋值。即字符数组名不可放在赋值号左边。

对于上面那个字符数组str_arr[],它的大小,即sizeof(str_arr)的值是17,也就是数组内所存字符串的大小(包括’\0’结束符)。
如果在头文件下,输出strlen(str_arr)的值,那么会输出16,也就是字符串内容的长度(不包括’\0’结束符)。

如果

cout<<str_arr[i]<<endl; 

或者

cout<<*(str_arr+i)<<endl; 

那么会输出字符数组中第i个字符。

这个地方有个有趣的事情是,字符数组str_arr[]中的空格并没有被编译器识别为’\0’结束符。那是因为,事实上’\0’结束符的编码是0x00,字符类型中并没有’\0’这个字符,它不是空格,而是一个空字符。
但是如果程序中使用

cin>>str_arr;

这样的语句输入一行带空格的字符串时,str_arr只能接收到第一个单词,这是因为输入流对象cin把空格(ascii码为0x20)约定为了输入结束的标志。

这个时候就应该使用逐行输入的函数了。在C的环境下,使用gets()函数是可行且便利的,但是vs2017中C++剔除了gets()函数,这样我们使用cin.getline()函数来输入带空格的字符串。在这个实例下,程序中可写:

cin.getline(str_arr,17,’\n’);


再分析字符串指针:

使用字符串指针处理的情况下,该字符串指针是是一个常指针。

cout<<str_pt<<endl; 

是可行的,但是

cin>>str_pt; 

是非法的(尽管编译器并不识别该错误,但是运行时会出错)。
像是

const char*str_pt= "What a nice day!";
str_pt = "Yes,it is.";

这样的语句,也是可行的。常指针指向的地址可改(即可以通过给指针二次赋值指向不同地址),仅仅是不能通过指针修改其指向的内容。再加上,字符串字面值常量本身是一个常指针常量,它可以赋给字符串指针,那么同理,字符数组名这个指针常量赋给字符串指针合法也是理所当然的了。
尽管字符串指针指向其所储存的字符串字面值常量的首地址,但是

cout<<str_pt<<endl;

并不输出该地址,而是输出整个字符串。如果想要获得该地址,则需要这样写代码:

cout<<(void*)str_pt<<endl;

而对于以下语句:

char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char *str5 = "abc";
const char *str6 = "abc";
cout << (str1 == str2) << endl;
cout << (str4 == str3) << endl;
cout << (str5 == str6) << endl;
cout << (str1 == str6) << endl;

它的输出结果是0 0 1 0 。两个字符数组名进行逻辑运算时,实际进行运算的是数组首地址;而字符串指针进行逻辑运算时,实际进行运算的是指针指向的内容(即字符串)。

另外sizeof(str_pt)的值是4,事实上,sizeof()函数所获取的大小,是字符串指针本身地址的大小,而所有指针本身的地址都是int型内存,故而输出4,即int类型单元内存的大小。

  • 26
    点赞
  • 81
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值