0%

C/C++ 复杂类型声明规则(1)-螺旋法则

“C/C++ 复杂类型声明规则” 将分为两节。第一节介绍螺旋法则声明规范,第二节介绍const的修饰关系。这两节内容,我都尝试以一种不用死记硬背,而是理解的方式去掌握。

本文参考自【初中生也能看懂的C/C++类型声明规则教学,很简单的!】 https://www.bilibili.com/video/BV1mB4y1L7HB/ 。里面通过一些例子介绍了螺旋法则。我将在此基础上加上我对其的解释,使其变得更加通俗易懂。

螺旋法则:

  • 第一步,找到变量名,如果没有变置名,找到最里面的结构

  • 第二步,向右看,读出你看到的东西但是不要跳过括号

  • 第三步,再向左看,读出你看到的东西,但是也不要跳过括号

  • 第四步,如果有括号的话,跳出一层括号

  • 第五步,重复上述过程,直到你读出最终的类型

举例1:

1
int *v[5];
  • 第一步:
1
2
int *v[5];
^

如上,我们找到了v是变量名。读作:v是……

  • 第二步,向右看,读出你看到的东西但是不要跳过括号。
1
2
int *v[5];
^^^

[5]意为是一个5个元素的数组。读作:v是一个五个元素的数组。

  • 第三步,再向左看,读出你看到的东西,但是也不要跳过括号。
1
2
int *v[5];
^^^^^

int *意为每个东西是一个指向int的指针。读作:v是一个五个元素的数组,数组每个东西指向一个int型指针。

  • 第四步,如果有括号的话,跳出一层括号。
1
int *v[5];

对于上面这个例子,无这一步。我们已经读完了:v是一个五个元素的数组,数组每个东西指向一个int型指针。

我们可以验证一下我们理解正不正确。我们可以用下列的代码给v数组赋值:

1
2
3
int a = 2023;
v[0] = &a;
printf("%p %p", &a, v[0]);

g++编译通过且运行正确,可见我们的理解没有问题。

举例2

1
int (*func)()
  • 第一步:
1
2
int (*func)()
^^^^

如上,我们找到了func是变量名。读作:func是……

  • 第二步:向右看,读出你看到的东西但是不要跳过括号。

向右边遇到括号了,不跳出括号,skip。

  • 第三步,再向左看,读出你看到的东西,但是也不要跳过括号。
1
2
int (*func)()
^

单独一个*意为“指向”。读作:func指向……

  • 第四步,如果有括号的话,跳出一层括号。向右看。
1
2
int (*func)()
^^

这样一组括号是函数的意思。括号内为空,说明这个函数没有参数。整个(*func)的左边是int,它是这个函数的返回值,是int。读作:func指向一个接收空参且返回值为int的函数。

我们可以验证一下我们理解正不正确。我们可以用下列的代码用匿名函数给func赋值:

1
2
3
4
5
int (*func1)();
func1 = []()->int{
return 2023;
};
printf("%d", func1());

g++编译通过且运行正确,可见我们的理解没有问题。

总结&一个网站推荐

螺旋法则五步骤;

当读的时候,看到[]意为一个数组, ()意为是一个函数,那么在主体的左侧肯定配套还会有一个返回值(当然,这个返回值也可能是一个复杂复合类型)。 *如果单独出现,意为指向,如果和类型出现,如int*,那就可以理解为指向int。

这里顺便推荐一个可以辅助阅读的网站:https://cdecl.org/ 。这个网站可以将表达式翻译成人话(英语),帮助大家的理解。但是总体来说只要会了螺旋法则,啥声明都能理解确切含义。