char, char[], char*, string, const char[], const char*,容易混淆,就整理出来偶尔看看嘿嘿。
目录
3. char[], char*, const char[], const char*, 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 (牛客网截图)