C语言声明解析

首先,来看一个简单的例子:
int a1;       /*a1是一个int*/
int a2[];     /*a2是一个数组,它的每一个元素是一个int*/
int * a3[];   /*a3是一个数组,它的每一个元素是一个int *(即,它的每一个元素是一个指向int的指针)*/
int (* a4)[]; /*a4是一个指针,它指向一个int数组*/

可能上面的3、4两行比较容易混淆,加不加括号其实区别很大。
比如说,如果我这么写:

int * a3[10];
int (* a4)[10];
对于上面的那一行来说,a3是一个数组,它的每一个元素是一个int指针,它一共包含10个这样的元素
在32位机上,一个指针型变量(不论它指向什么),他的大小都是4个字节,因此对于上面那一行,a3被分配的存储空间是:40个字节

对于下面的那一行来说,a4是一个指针,它指向一个int数组,而那个数组具有10个元素
根据上面的解释,任何类型的指针所占的存储空间是4个字节,那么这里也不例外,因此对于下面那一行,a4被分配的存储空间是:4个字节


接下来还有一个容易产生混淆的情况:

int i = 10;

const int * p1 = &i; /*p1是一个指向整型的指针,不能通过p1来修改i的值*/
int const * p2 = &i; /*p2是一个指向整型的指针,不能通过p2来修改i的值*/
int * const p3 = &i; /*p3是一个指向整型的指针,p3不能再指向除i以外的其他整型变量*/


上面的p1和p2其实是等价的,两种写法都正确。

关于const的辨析,可以总结为:

如果const出现在 * 的左边,则无法通过这个指针修改所指向的变量

如果const出现在 * 的右边,则这个指针从此以后无法再指向别的变量


同时,关于const这个关键词本身,我也想再作进一步的解释。

我认为这个词不应该被解释为常量,而应该解释为不可修改二进制保护


请看下面这个例子:

const int i = 10;
int * p = &i;
*p = 100;

printf ("%d\n", *p); /*打印100*/
printf ("%d\n", i);  /*打印100*/

上面这个例子的测试在VS2010及GCC 4.8.3上均通过了测试(注意,我们这里使用的是C编译器,而不是C++编译器)

编译器会在int * p = &i;这一行发出一个警告:(但不是错误

initialization discards ‘const’ qualifier from pointer target type(初始化丢失了const限定符)

然后我们成功地通过p修改了i的值

所以const常量并非真正的常量,它唯一的作用是防止你通过特定的标识符来修改内存中的某些值,在这里的情况是你不能通过i =  100来修改i的值

但你完全可以用上面所展现的这种曲径通幽的方法来达到修改的目的


接下来,我们来研究一下一个复杂一点的声明:

int * (*foo[10])(char *[], int);
那么foo究竟是个什么东西呢?
我们一步步地来分析:






所以foo的类型应该很明了了,我就不具体书写出来了(因为很长),但你现在肯定已经知道它究竟是个什么东西了。

那么我们该怎么分析一个C语言的声明呢?

我认为,应该从声明的两端寻找需要的信息,然后对这一过程,递归地进行下去

左端找:它是什么类型?int ?float ?某种你自己定义的struct ?,它是不是某种*(指针)?

右端找:它是不是一个[](数组)?,它是不是一个()(函数)?如果是函数,它接收哪些形参?

这里没有涉及诸如const,static,extern等限定符的情况,但即使出现了限定符,你也应该已经能够正确地解析它们了


最后,谈一谈为什么要这么做

为什么有些人要写一些像这样复杂的声明,然后我们还要去学习怎么解释这样复杂的声明呢

这算不算是一种奇技淫巧呢?

坦白的讲,我认为——

这样的声明,就像玩杂技一样,上下(左右)翻飞,令人眼花缭乱

但是我还想说,C(以及C++)

就是一门奇技淫巧的语言

在那个年代,内存受限(往往以KB计算),CPU性能受限,编译器的功能受限(以至于这些所谓的高级程序设计语言,在当时其实是很不方便的)

人们不得不想出很多办法,来实现一些语言中没有的特性,比如说人们就用到了函数指针这种东西,它后来几乎成为了奇技淫巧的代名词

奇技淫巧,毕竟也是一种,也是一种,它们在特定的历史时期,解决了特定的问题

它们至今还活跃在你所使用的编译器的代码中,你所使用的操作系统的代码中

我们在面对奇技淫巧的时候,要端正心态,不要一味地去追逐奇技淫巧,从而达到炫技的目的

也不能一味地排斥一些能够解决特定问题的特定技术

比如上面关于较复杂的C语言声明的解析,就能够帮助你读懂许多C语言的源码

然后你才有能力思考,代码的原作者为什么要这样设计?


码,为人所用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值