`
jiagou
  • 浏览: 2532930 次
文章分类
社区版块
存档分类
最新评论

typedef和const之间的trap

 
阅读更多

博客好久没有更新了,主要是因为工作忙,即便不忙也要看看书,工作了才发现好多东西根本就会直接忘记,因为我们工作用不到!比如c++的东西,现在连虚函数表都不快不记得了,惭愧咯!而且我还发现工作了,看书反倒成了一种非常好的休闲了,不过希望我的朋友,同学们都好.

现在就说说typedef和const之间的那么一道陷阱,而且还很深!

现在也是找工作的时间了,弄清楚这个还是很有好处的,或许很多公司就会用这个来欺负"弱小".

记得好像是<c专家编程>里面说提及了这个问题,上面说typedef和const一起使用之后const使用对象会和想象的不一样,具体的不记得了,n久以前看的书了,hoho,不记得了.

现在我就来说说我的理解,之间的代码就不注意命名规范了,还有一些工作的代码肯定也是不能贴了.

先给一个引子,如果我有一个全局变量,是一个二维数组,现在的问题就是,老板不喜欢全局变量,他要弄成一个static变量,需要封装一下,怎么弄,比如这个二维的变量是:

那么我现在就要让这个静态函数能穿越文件,就用一个函数封装起来,然后,返回这个变量的地址,要么就用直接值拷贝的方法,把值按位复制除去都行,如下操作?

明显不行,二者不是一个东西,int**是一个二维指针,而我的苹果myapple却是一个int (*)[8]类型的变量,这个问题我不知道一般的c语言的书籍里面涉及了否,不过如果好多c++的书籍里面还是涉及到了的.

那么现在的问题就很简单了,只要给一个适当的返回类型就ok了.这样?

有点简单,有点粗暴,却不那么有效!

引入typedef,我们可以把一个很复杂的类型用typedef来实现类型的替代,记住是typedef不是define.先定义类型,然后就是作为函数的返回值就ok咯.

那么就肯简单了,如下给出我们一个正确实现:

如此便ok了.

故事到这里就结束了?还没有!

继续看,我上面的type的定义里面加了一个const,下面我定义一个不加const的类型:

这两个类型的差别仅仅是一个const吗?当然不是,hoho,差别在与const是在星星(指针的星号)前后的问题了,type的类型决定了该类型定义的对象不可修改,因为它是在星号前面,或者说它修饰的是对象本身.而type_2呢,在做类型定义myapple_2的时候加上了const,是不是myapple不能改变了?不是,而是,指针不可变!二维的或许有点复杂,我们用一维指针来作为示例:

xp可以说是一个自定义类型,我在定义xp1的时候加上了const修饰,那么从上面的程序来看,1处是没有问题的,在typedef之后,再在变量定义时候加的const实际上是被编译器放在了星号自后了,那么这个const就表示他修饰的是这个指针而不是变量本身,结果2处就错了,因为我视图修改指针xp1.

那我要把const应用与变量而不是指针,就要把const在typedef的时候带上,放星号前面,那么const就修饰的是变量了,如下:


这样的话,2处就会报错,原因上面已经说过了.

回到二维的,也就比较好理解了


const修饰的是后面数组的地址了.自然也就相当于:


如下,同样也可以给出一个例子:


同样:


这个const就是修饰的变量的值了,1处自然也不对了.

最后还有一个问题要说明的是typedef char *xp;得到的xp类型,可以给他赋值变量的地址,或者数组首元素的地址:


上面的程序里面,只要是能表示一维的都可以给myxp赋值,但是类型一定要完全一致.这里容易出两个问题:
1.一维指针但是类型不一致,当然了,c语言给我们提供了强制类型转换;
2.取数组名的地址,再给myxp赋值,这样也是不对的,因为维度不匹配:


1处就明显不对了,但是有人说,数组名和数组名取引用是一个值啊!却是,但是,对于编译器而言,两者是不一样的,a是char*,而&a是char (*)[100]的类型,a+1得到的是a[1]的地址,而&a+1得到的是什么?我想稍微注意点的同志们都知道是下一个100大小的数组的首地址了,也就是a[100]这个本不应该存在的地址了,而且仅仅是值一样,还是一个char (*)[100]的类型.这个就不说远了.有需要的可以再写一篇文章了.

对于typedef一个二维的指针也可以用类型的方法初始化:

这里1和2自然也是不对的,因为他们的维度也不匹配!

就说这么多吧,好累,下班手工回家咯!
希望大家有什么意见,可以提出来,一起学习.

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics