C++字符 · 字符串

char, char[], char*, string, const char[], const char*,容易混淆,就整理出来偶尔看看嘿嘿。

目录

1. char 数据类型

2. char 与 string

3. char[], char*, const char[], const char*, char**

声明和赋值方式

访问其中一个字符和遍历字符串※

char**

const  char (牛客网截图)


1. char 数据类型

字符:char类型的变量,只能容纳一个字符,以数字的形式存储在内存中。

char a= 'A';
cout << a << endl;     // 输出A
char asave = 65;
cout << asave << endl; // 输出A

2. char 与 string

字符串:string类型,以'\0'为终止符。注意:字符'0'的ASCII为48,而空终止符ASCII为0

字符串连续存放,字符串"HelloChar"长度为9个字符,但实际占用了10个字节的内存。

单引号:字符char a = 'A';被存储为[A]   (65)

双引号:字符串string str = "A";被存储为[A][\0]   ([65][0])

3. char[], char*, const char[], const char*, char**

声明和赋值方式

char[] 字符型数组变量来表示字符串,初始化之后可再次赋值,但只能逐个元素赋值。

const char[] 声明方式同理,表示只读字符串,初始化之后不能更改在内存单元中的值。

  • char str[] = "ABC";    // cout << str  输出ABC char[4] 
    char str[] = {"ABC"};  // cout << str 输出ABC char[4]
    char str[] = {'A','B','C','\0'}; // 要加 \0 才构成字符串 char[4] d
  • // ❌报错!!数组名不能作左值
    char str1;
    str1 = "abc"; 
    // ✅想初始化或再次赋值只能单个元素赋值(如下行)
    str1[0] = 'B';      // cout << str1 输出BBC复制代码
  •  const char str3[] = "ABC"; // 不可以char cosnt str3[]
     str3[0] = 'B';  // ❌报错!!const类型字符数组不能改值

 

char* 字符指针变量,可改变指针的指向,也可更改指针指向的内存单元中的值;

const char* 可更改指针的指向,但不可更改指针指向的内存单元中的值

  • char str[] = "ABC";
    char *p1 = str;  // C++11不建议 char *p1 = "ABC" 这种写法(能运行,但黄牌警告⚠️)
    // 💖顺序是:1.分配内存给字符指针;2.分配内存给字符串;3.将字符串首地址赋值给字符指针;
    const char *cp = str;
*p1: A是取p1指向的地址存的值,即str[0]
p1: ABC,str: ABC,&str[0]: ABC通过首地址输出整个字符串
&p1: 0x7fff5fbff660是p1这个指针的地址
&str: 0x7fff5fbff66c是取字符串首位的地址
  • 遇到👇下面这行代码,编译器会从第一个元素起,把 A B C D E \0 逐个填入s数组。
    char s[10] = "ABCDE"; // 编译器给数组分配10个单元(10Byte),每个单元的元素数据类型为char(字符),
    char *p;  // 声明一个char型指针变量p,只占4字节(4Byte)
    p = s;    // 让p指向数组0号元素的内存
    cp = s;
    printf("%s",s);     // 输出ABCDE。"%s":用字符串首地址输出字符串,本质是:printf("%s",地址)
    printf("%s",&s[0]); // 输出ABCDE。数组名代表数组所在内存位置的首地址
  • 😡注意:👇char指针p指向字符串常量的内存,可以通过p输出这个字符串,但是不能更改它(不能写)。
    char m[15], *p=m;  p="Hello"; // ✅char m[15]; char *p=m; p="Hello";
    char m[15], *p;  p=m="Hello"; // ❌数组名不可被赋值(上面提过喔,是不是又没看出来?)

     👆代码出错,因为先声明了char数组m[15],此时m[15]已有一块内存。而数组名m代表一个指针常量,指向m[15]第一个元素的地址,即:m是&m[0]。之后再给m="Hello"这样赋值相当于给一个常量赋值。

  • 指针p和cp也保存这个字符串的首地址,这个地址单元的数据是一个字符。
  • 数组名可以复制给指针,表示地址,但是不能反过来给数组名赋值。
printf("%p",s) ;    // 0x7fff5fbff6ee  字符串首地址
printf("%p",p) ;    // 0x7fff5fbff6ee
printf("%p",&p);    // 0x7fff5fbff6d0  指针变量p本身所在的内存单元
printf("%p",cp) ;   // 0x7fff5fbff6ee

 

访问其中一个字符和遍历字符串※

  • 取值并更改该字符,指针指向不动
// 注:原char s[10] = "ABCDE"; char *p = s;
s[2] = 'A';      // ABADE
*(p+2) = 'A';    // cout<< p 输出 ABADE 
// 👆*(p+2)先取p指向的地址后面两位的地址内容,然后更改地址内容,'C'to'A'
// ❌若 char *p = "ABCDE"; 则不能通过p修改字符串,*(p+2) = 'A';和p[2] = 'A';会报错

for(int i = 0; i<5; i++){// 遍历
    cout << p[i] << endl; }// 等价于cout << s[i] << endl;
  • 改变指针指向,不改变值
// E1
cout << p << endl;       // ABCDE
cout << *(++p) << endl;  // B  先将p指向的地址后移1位,再取地址内容‘B’
cout << p << endl;       // BCDE 此时p指向s[1],所以输出从s[1]地址为首的字符串
cout << s << endl;       // ABCDE 未改变字符串值,只移动了指针指向的位置
// Eg2
cout << p << endl;       // ABCDE
cout << *(p++) << endl;  // A  先取地址内容‘A’,后将p指向的地址后移1位
cout << p << endl;       // BCDE 此时p指向s[1],所以输出从s[1]地址为首的字符串
cout << s << endl;       // ABCDE 未改变字符串值,只移动了指针指向的位置
  • 字符数组与int数组某个区别

 char s[]: cout << 数组名s,输出数组字符串内容 ABCDE 
 int a[]: cout << 数组名a,输出数组元素首地址;

int a[] = {1,2,3};
cout << a << endl;       // 0x7fff5fbff6e0复制代码

char**

二级指针保存的是一级指针的地址,它的类型是指针变量,而一级指针保存的是指向数据所在的内存单元的地址,虽然都是地址,但是类型是不一样的。

const  char (牛客网截图)

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值