现在的位置: 首页 > 综合 > 正文

C++ typedef的应用

2017年08月20日 ⁄ 综合 ⁄ 共 2541字 ⁄ 字号 评论关闭
第一个百度上的官方解释
原问题描述:
typedef struct node{
datatype data;
struct node *lchild,*rchild;
}bintnode;
上面是说用bintnode来代替node吗?什么意思?
完整代码,书上的
typedef char datatype;

typedef struct node{
datatype data;
struct node *lchild,*rchild;
}bintnode;

typedef bintnode *bintree;

typedef struct{
int front,rear;
bintree data[queuesize];
int count;
}cirqueue;

typedef的语法规则其实很简单,一句话来说就是定义对象的语法前加关键字typedef,剩下的不变,原本定义的对象标识符换成类型标识符,对应语义从定义一个对象改成定义一个类型别名。typedef看起来复杂根本原因是对象定义的语法比较复杂,例如分隔符*和[]的用法。
typedef struct node{
datatype data;
struct node *lchild,*rchild;
}bintnode;
对应的对象定义:
struct node{
datatype data;
struct node *lchild,*rchild;
}bintnode;
去除bintnode来看就是一个类型struct node的完整描述。加上了bintnode来看,表示定义了一个struct node类型的对象bintnode。
现在前面有typedef,因此这个bintnode不是对象名而是类型名。也就是定义了一个类型别名bitnode,实际上指的就是struct node这个完整类型。
typedef定义的类型别名在作用域内和被定义的原类型语义上等价,都是表示同一个类型的名称。这里typedef之后bitnode可以和struct node互相代替(注意在C++中,如果同一命名空间内类型名和对象名没有重复,那么struct可以省略,struct node等价于node)。
更复杂一点的:
struct node{
datatype data;
struct node *lchild,*rchild;
}bintnode, *bintree;
注意定义对象时*修饰对象本身而不是修饰类型。因此这里定义了struct node对象bintnode和struct node*类型的对象bintree。
对应的类型定义:
typedef struct node{
datatype data;
struct node *lchild,*rchild;
}bintnode, *bintree;
这里定义了类型别名bintnode表示完整类型struct node,以及bintree表示类型struct node*。
拆开来就成了
typedef struct node{
datatype data;
struct node *lchild,*rchild;
}bintnode;

typedef bintnode *bintree;
这种写法看起来应该稍微清楚了一点。
至于下面的cirqueue,和上面的bintnode类似,只是这里省略了结构体名称,是一个匿名类型。这样写的主要好处是类型名可以省略struct(C++里面不这样写也可以省略)。


第二个是一个例子
typedef struct OLNode{
int i,j;
int e;
struct OLNode *right,*down;
}OLNode,*OLink;
这里的*OLink是什么意思?OLink a;这样定义的变量a算是什么,怎么回事?

给你解释一下:
定义完上面的Struct后,将这个定义命名为 OLNode,或者 *OLink,后者是一个指针。当你用这个定义a的时候,就是 OLink a,就是定义a为一个指向 stuct OLNode的指针。
明白了吧?这样写只是为了让写指针的时候少写个*而已。一般老程序员常常喜欢这么做。希望你能满意!
追问
那p=(OLink *)=malloc(sizeof(OLnode));得到的p不是指向OLnode类型的指针的指针吗? (M.rhead=(OLink *)malloc((m+1)*sizeof(OLnode)))得到的M.rhead不应该是栈底指针吗?为什么又可以像for(i=1;i<=m;i++)M.rhead[i]=M.chead[i]=NULL;这样把栈当做数组访问呢?这和上面的那种结构体的定义方式有什么关系吗?我试的时候把结构体定义成struct OLnode{int i,j,e; 。。。} *OLink;为什么不能M.chead[i]这样用了呢?
回答
因为看不到你的全部源程序,我就根据你问的几个代码直观地解释一下吧:

p=(OLink *)malloc(sizeof(OLnode))
这个是声明一段内存存放OLnode数据并且获得它的指针

M.rhead=(OLink *)malloc((m+1)*sizeof(OLnode))
这个是获得第m+1个内存段的指针(并且声明内存空间),如果你只用到m个内存段,那么这个地址就可以看成是你要用的内存段的最后的地址。(注:每个内存段都为存放一个OLnode的数据而准备)。另外,并不是像你想象的按堆栈方式(自下而上)排列,这个是普通的内存线性排列。
(因为内存的图形缘故,很容易让人想到是一个栈,而误解,不过还是不太清楚那个最后的地址怎么就变成数组了……)
for(i=1;i<=m;i++)
M.rhead[i]=M.chead[i]=NULL
这个其实就是将指针清空。本来是指向前面定义的内存段的,现在清零。注意:一定要在这个之前释放你之前声明的内存空间,否则会出现内存泄露!
因为我前面说过,这个内存是线性排列的,所以当然可以用这种循环来清空。

最后一个问题,如果你前面不用typedef别名,当然无法用*OLink在struct后面定义别名。stuct只能定义一个名字。要定义别名一定要用tyepdef。

OK,就是这样,因为没有源程序,我不能保证都解释完整了。希望你能满意。
提问者评价
谢谢了,讲的挺好的,挺清楚的。这是数据结构中的一个例子,没弄明白,书上也没有解释。太谢谢了。


【上篇】
【下篇】

抱歉!评论已关闭.