浅探C++中const、char与*的排列组合

写在前面

来自于C++课上提出的问题:char *pconst char *pchar p[]const char p[]有何区别。本文通过测试编译器是否报错和使用typeid(VAIBLE_NAME).name()输出的方式来从能否更改指向的地址能否更改指向的内容两个角度来测试

char *p1
const char *p2
char *const p3
char const *p4
char p5[]
const char p6[]

六者的区别。

写在中间

需要注意的是,在一些相对基础(内容浅显、易于理解)的课中,可能会将数组类型([])和指针类型(*)混为一谈,实际上这是错误的。在底层他们的受处理方法完全不同。

对于数组类型,无论定义时是否指定长度或是否初始化(指定长度和初始化至少做一个),数组都不可以更改指向的地址。如果数组中的数据类型不是const类型,则可以更改指向的内容

数据类型 能否更改指向地址 能否更改指向内容 typeid(VAIBLE_NAME).name() sizeof(VAIBLE_NAME)
char * Pc 8
const char * PKc 8
char *const Pc 8
char const * PKc 8
char [] A3_c 3(关于为什么是3可以参照下面代码)
const char [] A3_c 3(同上)

关于typeid(VAIBLE_NAME).name()输出内容的含义,我们可以参照chatGPT给出的解释:

为什么不问问万能的chatGPT呢

至于sizeof(VAIBLE_NAME)返回的内容我们可以视作该变量占用的字节数。

我们可以发现,连续的char constconst char是完全相同的,其均代表更改指向的内容这一操作不被允许。而类似* const 的结构代表更改指向的地址这一操作不被允许。

写在后面

本文使用的测试代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <typeinfo>
using namespace std;

int main()
{
char c0 = 'b';
char *p1 = NULL;
const char *p2 = NULL;
char *const p3 = NULL;
char const *p4 = NULL;
char p5[] = "p5";
const char p6[] = "p6";

p1 = &c0;
p2 = &c0;
// p3 = &c0;
p4 = &c0;
// p5 = &c0;
// p6 = &c0;

*p1 = 'a';
// *p2 = 'a';
*p3 = 'a';
// *p4 = 'a';
*p5 = 'a';
// *p6 = 'a';

cout << "p1 " << typeid(p1).name() << ' ' << sizeof(p1) << endl;
cout << "p2 " << typeid(p2).name() << ' ' << sizeof(p2) << endl;
cout << "p3 " << typeid(p3).name() << ' ' << sizeof(p3) << endl;
cout << "p4 " << typeid(p4).name() << ' ' << sizeof(p4) << endl;
cout << "p5 " << typeid(p5).name() << ' ' << sizeof(p5) << endl;
cout << "p6 " << typeid(p6).name() << ' ' << sizeof(p6) << endl;
cout << "c0 " << typeid(c0).name() << ' ' << sizeof(c0) << endl;
return 0;
}

被注释掉的内容即为不被允许的操作。

什么常量指针、指针常量,作者本不应该给读者设置门槛。


浅探C++中const、char与*的排列组合
https://tanyuu.github.io/2023.01-06/浅探C++中const、char与Asterisk的排列组合/
作者
F Juny
发布于
2023年3月5日
许可协议