复杂类型例子 c语言,C++实例:c++数据类型及复杂声明推演

::max() << std::endl;

std::cout << "Minimum short value: " << std::numeric_limits::min() << std::endl; 理解类型声明

简单的类型声明很容易理解:

int i

然而,有时也会有十分复杂的类型声明:

double **d[8] //hmm...

char *(*(**foo [][8])())[] //augh! foo到底是什么?

为了理解上面的声明,可以遵循下面的三个规则:

1.从变量名开始(在上例中就是d或者foo)

2.以数据类型结尾(double或者char)

3.如果可以的话向右,必须的话则向左(括号可能会让你改变方向)

例如:

表达式 意义

double **d[8];

double **d[8]; d 是 … double

double **d[8]; d 是 8维数组 … double

double **d[8]; d 是 8维数组且成员为 指针且指向 … double

double **d[8]; d 是 8维数组且成员为 指针且指向 指针且指向 double

另外一个例子:

表达式 意义

char *(*(**foo [][8])())[]

char *(*(**foo [][8])())[] foo 是 … char

char *(*(**foo [][8])())[] foo 是 一个数组 … char

char *(*(**foo [][8])())[] foo 是 一个数组且成员为 8维数组 … char

char *(*(**foo [][8])())[] foo 是 一个数组且成员为 8维数组且成员为 指针且指向 … char

char *(*(**foo [][8])())[] foo 是 一个数组且成员为 8维数组且成员为 指针且指向 指针且指向 … char

char *(*(**foo [][8])())[] foo 是 一个数组且成员为 8维数组且成员为 指针且指向 指针且指向 函数且返回 … char

char *(*(**foo [][8])())[] foo 是 一个数组且成员为 8维数组且成员为 指针且指向 指针且指向 函数且返回 指针且指向 … char

char *(*(**foo [][8])())[] foo 是 一个数组且成员为 8维数组且成员为 指针且指向 指针且指向 函数且返回 指针且指向 数组 … char

char *(*(**foo [][8])())[] foo 是 一个数组且成员为 8维数组且成员为 指针且指向 指针且指向 函数且返回 指针且指向 数组且成员为 指针且指向 char

译注:

我们也可以采用另外一种方法就是层层类型定义的方法来解读,不过是从外向内的.比如例子1:

typedef double * pDouble;

typedef pDouble* ppDouble;

typedef ppDouble a8ppDouble[8];

a8ppDouble d;

第二个例子:

typedef char * pchar;

typedef pchar apchar[];

typedef apchar * papchar;

typedef papchar fpapchar();

typedef papchar (*pfpapchar)();

typedef pfpapchar * ppfpapchar;

typedef ppfpapchar a8ppfpapchar[8];

typedef a8ppfpapchar aa8ppfpapchar[];

typedef aa8ppfpapchar foo;

附文:

下面是对Steve Friedl的参考文章的部分译文,因为这里也同样的是解说这两个例子,不过对于规则上述说更详细。

基本和派生类型

基本类型就是上边提到的那些基本类型,这里还包括了struct,enum和union(译注:因为这个说明是针对c语言的,所以对于c++来说还要加上一个class类型)

一个声明只能定义一种基本类型,并且它总是出现在声明式的最左边。基本类型可以被派生类型扩张或者说是修饰,并且c有三种派生类型:

* 指针且指向(pointer to...)

这里*表明这是一个指针,而且不言自明地它要指向某个东西

[] 数组且成员为(array of...)

数组可以是已定维数的--[10]--也可以是未定维数的--[],但是维数在我们理解声明具体含义的时候不是那么重要。典型地我们会把维数包含在声明里。这样可以明了的说“数组且成员为”某些东西。

() 函数且返回(function returning...)

函数通常是由一对圆括号来表明的--尽管可能在里面发现参数类型。参数列表其实在我们理解声明的时候是不重要的,可以忽略。应该注意到的是函数的括号和分组改变优先级的括号是不一样的:分组括号总是包围变量而函数括号却总是在变量名(即函数名)的右边。

如果函数不返回值则它是无意义的(我们可以使用void来表示返回为空)。

一个派生类型总是修饰一个基本变量或者另外一个派生变量。我们在理解声明的时候一定要包括介词(to,of,returning)。说“指针”而不是“指针且指向...”会导致你的声明分离。

操作符的优先级

几乎每一个c程序员都很熟悉操作符的优先级表。比如乘除的优先级要高于加减,但是括号可以改变这个优先级。这个对于通常的表达式很自然,但是这个规则也可以运用到声明语句中--它们是类型表达式而不是计算表达式。

数组符号[]和函数符号()比指针*有更高的优先级,这样我们可以推导出一些规则(这个规则和上边所提的是一样的,这里不再啰嗦,离子的推衍也不再重复)。

抽象声明

C标准也支持抽象声明。它可以用在需要类型描述但是又不需要实际变量的情况下--cast,抛掷,和作为sizeof的参数。比如:

int (*(*)())()

对于上边的问题--从哪里开始,答案是找到一个变量名可以放得下的地方,然后把它当成一个通常的声明。只有一个地方可以放置这个变量名并且找到它也是直截了当的。遵循以下语法规则:

- 在*的右边

- 在[]的左边

- 在函数操作符()的左边

- 在分组括号()的内部

由上面的例子我们可以看到有两个地方符合前三条规则:

int (*(* • ) • ())()

但是如果考虑则四条,则只有左边的位置符合了。

int (*(*foo)())()

它表示:

foo是 指针且指向 函数且返回 指针且指向 函数且返回 int

语义限制

注意不是所有的派生组合都被允许的.这样就可能声明一个合乎语法却没有语义内涵的东西来:

--不能有 数组且成员为函数

使用 数组且成员为 指针且指向 函数且返回.... (译注:但是我们知道函数的地址就是函数本身,所以可以说 数组且成员为 函数指针且返回)

--函数不能返回函数

同样使用函数指针代替

--函数不能返回数组

可以使用 函数且返回 指针且指向 数组且成员为...(译注:同样地我们知道数组名同时也是数组首元素的地址,还是该数组的地址)

--数组中只有最左的[]可以是未定义的

--void是限制类型,它只有在和指针*以及函数()在一起时才有效.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值