专栏首页zlmai的专栏搞清C++中指针、数组、字符串的关系
原创

搞清C++中指针、数组、字符串的关系

字符串是存储在内存中连续字节的一系列字符,C++处理字符串的方式有两种:

1、来自C语言的C-风格字符串;

2、基于string类库中的方法。

本文主要讲第一种。

在C++中定义一个字符串的语句,可以是:

char arr[] = "aaa"; 

或者是:

char arr[4] = "aaa"; 

或者是:

char arr[4] = {'a','a','a','\0'};  // 注意,最后一个元素一定要是'\0',否则arr不表示字符串

这三种写法都是等效的。

但怎么表示这个字符串呢,有两种C-风格字符串的表示方式:

1、使用带双引号的字符串表示,比如"aaa";

2、使用指向字符串第一个字符的指针表示,比如arr(arr是数组名,也是指向数组第一个元素的指针,也是指向arr这整个数组的指针,其值实际为"aaa"字符串所在的内存地址)。

但是在一些时候,字符串、指针和数组的关系我们常常搞混,下面通过一些典型问题来展示它们间的关系:

1、字符串-数组:

#include <iostream>
int main()
{
    using namespace std;
    char arr[] = "aaa";
    cout << arr << endl;
    cout << &arr <<endl;
    cout << arr[0] << endl;
    cout << &arr[0] <<endl;
    return 0;
}

输出:

aaa(arr等同于字符串"aaa",是一个常量,所以直接输出"aaa")

0x7ffeefbff5d8(arr其实还是指向arr整个数组地址的指针,也是指向arr中第1个元素地址的指针,所以&arr输出了其指向的地址值)

a(输出arr第一个元素)

aaa(这个有点不好理解,&arr[0]其实是 char* 类型(指向第一个元素的指针)。 cout会把char*当做字符串,从指向处开始处理,一直输出直到\0,所以输出"aaa"。如果对它解引用 * &arr[0] 就得到单个字符char 类型。或者也可以这么理解:

因为arr[1] = *(arr + 1),所以有&arr[1] = arr + 1,所以有&arr[0] = arr,所以输出相同)

代码中的双引号做了三件事:

1)申请了空间(在常量区),存放字符串"abc";

2)在字符串尾加上'/0';

3)返回字符串地址给arr。

2、字符串-指针:

#include <iostream>
int main()
{
    using namespace std;
    char arr[] = "abc";
    char* pt = arr;
    cout << *pt << endl;
    cout << pt << endl;
    cout << *pt + 1 << endl;
    cout << *(pt + 1) << endl;
    cout << arr[1] << endl;
    cout << &arr[0] << endl;
    cout << &arr[1] << endl;
    return 0;
}

输出:

a(因为arr也是一个指向首元素地址的指针,赋值给pt后,*pt就是取首元素的值)

abc(同输出arr)

98(*pt为a,+1后转为整型,即97+1=98)

b(*(pt + 1) 相当于 arr[1])

b(数组第二个元素值)

abc(&arr[0]其实是 char* 类型(指向第一个元素的指针)。 cout会把char*当做字符串,从指向处开始处理一直输出直到\0,所以输出"abc")

bc(&arr[1]也是 char* 类型(指向第二个元素的指针)。 cout会把char*当做字符串,从指向处开始处理一直输出直到\0,所以输出"bc")

3、数组-指针:

1)

#include <iostream>
int main()
{
    using namespace std;
    char* p;
    p = "aaa";
    cout << p << endl;
    return 0;
}

2)

#include <iostream>
int main()
{
    using namespace std;
    char arr[4];
    arr = "aaa";
    cout << arr << endl;
    return 0;
}

为什么1)可以编译通过而2)会报错?

因为字符串常量"aaa"表达式使用的值其实是这个字符所存储的地址(在常量区),而不是这个字符本身。所以,可以把字符串赋值给指向字符的指针p,而不能把字符串赋值给一个字符数组名(因为字符数组名虽然也是一个指针,但它是一个(指针)常量,是不可变的,放在等号左边会报错)。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • C++中关于几种输入方法的总结

    C++中有很多关于输入的函数,比如cin、cin.get()、cin.getline()、getline()、gets()等等,很容易搞混,下面分别总结下,欢迎...

    zlmai
  • 理解PHP的延迟静态绑定

    static::中的static其实是运行时所在类的别名,并不是定义类时所在的那个类名。这个东西可以实现在父类中,能够调用子类的方法和属性。

    zlmai
  • 前端十大经典排序算法

    冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是...

    enoyo
  • java学习之数组元素排序,冒泡排序和选择排序

    吾爱乐享
  • 快速排序(quick sort)C++实现

    每次选一个轴pivot(我选数组的第一个元素arr[p]),遍历其余数组元素使得比arr[p]大的数都在arr[p]的右边,比arr[p]小的数都在arr[p]...

    kalifa_lau
  • swap()交换两个变量的方法汇总

    sr
  • OJ刷题记录:L1-206-学霸递情书(15分)

    题目要求: 李雷和韩梅梅坐前后排。上课想说话怕老师发现,所以改为传小纸条。为了被老师发现他们纸条上说的是啥,他们约定了如下方法传递信息: 将26个英文字母(...

    英雄爱吃土豆片
  • Java中选择排序,冒泡排序等排序方法示例

    用户1696846
  • 算法菜鸟的烂笔头

    cnguu
  • 数据结构与算法——冒泡排序

    第一趟排序后,最后一项已经是最大值,第二趟排序时只需要对前n-1项进行排序,得到arr数组中的数据顺序为 arr={5,4,8,3,9,10 }

    C you again 的博客

扫码关注云+社区

领取腾讯云代金券