C声明变量的用法体现C++封装思想
2011-03-18 17:55
183 查看
在linux2.6.10中看到这样一些代码;
/mm/slab.c中定义了struct kmem_cache_s{......};
而/include/linux/slab.h中又作了如下定义:typedef struct kmem_cache_s kmem_cache_t;内核其他地方又引用
的都是“kmem_cache_t”,且引用的头文件都是/linux/slab.h,问题由此来了,以前编译一些文件,都是直接在.h文件中
定义一个类型(结构体什么的),还没碰到过用typedef 声明一个类型,而在与.h文件名相同的.c文件下定义,别的文件通
过include此头文件来声明一个变量。这跟以前有什么区别呢?在fed10下做个试验:
/*myprintf.c*/
#include<stdlib.h>
struct kmem_cache
{
int i;
int j;
} ;
/*myprintf.h*/
#ifndef _MYPRINTF_H_
#define _MYPRINTF_H_
typedef kmem_cache kmem;
#endif
/*test.c*/
#include"m
4000
yprintf.h"
int main()
{
kmem men;
men.i=2;
men.j=3;
printf("%d<--->%d/n",men.i,men.j);
return 0;
}
编译下 gcc -Wall -o test test.c myprintf.c
test.c:在函数‘main’中;
test.c:4:错误:‘men’的存储大小未知
test.c:4:警告:未使用的变量‘men’
ok,不出所料,出错了。。。看来有新东西可以发现了,把.c文件声明的类型放到.h文件中去,编译通过,以前的写法看来
是没错的,但linux上这种写法有什么用处呢?继续搜索内核代码的声明,发现其他文件声明都是kmem_cache_t *cache
之类的,声明的都为此类型的指针变量,为什么声明都是指针呢?而不是某个变量?原来指针变量本身也是有存储空间来存
放它的,要不指针变量一旦变化,那它的值存哪呢?而且存储空间是固定的,有疑问的可以自己验证下,代码如下:
#include<stdio.h>
int main()
{
int *p1;
char *p2;
short *p3;
printf("%d,%d,%d",sizeof(p1),sizeof(p2),sizeof(p3));
return 0;
}
32机指针变量所占的存储空间固定占4字节,所以gcc编译器就不需要检查它的存储大小了,直接分配4字节空间,并标明空
间放的内容是kmem类型的,如果是声明变量的话,编译器只能找到.h文件中的类型声明,而.h文件却只有个typedef定义,
无法得知此类型所占存储空间大小,所以报错:test.c:4:错误:‘men’的存储大小未知。声明个指针有什么好处呢?继续
查找代码,发现指针的值都是通过调用函数kmem_cache_t *kmem_cache_create()的返回值进行赋值,此函数在slab.h
中是有声明的。更改测试代码:
在/*myprintf.c*/文件中加入
kmem* kmem_create(int a,int b)
{
kmem *pa = (kmem*)malloc(sizeof(kmem));/*为指针申请一个kmem大小的内存空间*/
pa->i=a;
pa->j=b;
return pa;
}
在/*myprintf.h*/
kmem *kmem_create(int,int);
修改/*test.c*/
#include"myprintf.h"
int main()
{
kmem men;
int a,b;
a=2;b=2;
men=kmem_create(a,b);
printf("%d<--->%d/n",men->i,men->j); /*注意这行*/
return 0;
}
兴奋的编译下,gcc出新错误了;
test.c:在函数‘main’中
test.c:8:错误:men指向不完全类型的指针
由此看来这种类型声明的指针是不允许访问类型里面的成员,它只能做为一个单纯的指针,送给给类型定义下的.c文件下的处
理函数进行处理。类型的成员对外是不透明,封闭的,.c文件只给提供功能接口函数,提供所需要的功能就OK了,这跟C++
里面类的封装思想很相似。
最终的测试代码如下:
/*myprintf.c*/文件
#include<stdlib.h>
struct kmem_cache
{
int i;
int j;
} ;
kmem* kmem_create(int a,int b)
{
kmem *pa = (kmem*)malloc(sizeof(kmem));/*为指针申请一个kmem大小的内存空间*/
pa->i=a;
pa->j=b;
return pa;
}
int kmem_add(kmem*pa)
{
return pa->i+pa->j;
}
/*myprintf.h*/文件
#ifndef _MYPRINTF_H_
#define _MYPRINTF_H_
typedef kmem_cache kmem;
kmem*kmem_create(int,int);
int kmem_add(kmem*);
#endif
/*test.c*/文件
#include"myprintf.h"
int main()
{
kmem men;
int a,b;
a=2;b=2;
men=kmem_create(a,b);
a=kmem_add(men);/*新加入的行*/
printf("%d /n",a);
return 0;
}
编译下,成功通过生成test执行程序,运行程序结果正确!
此外还想到另外一个问题,指针变量本身所占空间的问题。例如声明一个int型指针变量int *pa; 存储pa变量的空间应该
有个地址给指明,指针变量所占空间是4个字节,可空间返的地址只有一个字节空间,明显不等,我们都知道32位地址总线
指向的存储空间是2^32字节空间,每个32bit的地址占一个字节存储空间,所以指针所占空间返回的地址应该是个首地址,
它应该占用后3位地址。因此可以这样想象 当声明一个指针变量时,指针变量的值就是个32bit的值,固定占4字节空间,编
译器会分配4个字节的空间,并把第一个字节空间的地址当成存储指针变量本身的空间地址;当声明一个其他类型变量(如整
型变量,结构体变量)时,编译器会计算整型或结构体所占空间大小,并分配出的类型大小的空间,同样把第一个字节空间的
地址当成存储此变量本身的空间地址。呵呵,有点绕口。。。
相关文章推荐
- Java经典封装JDBC模板(充分体现面向对象思想)
- C++编程思想3-利用C++进行文件操作封装C函数
- Java经典封装JDBC模板(充分体现面向对象思想)
- C++编程思想3-利用C++进行文件操作封装C函数
- C++编程思想3-利用C++进行文件操作封装C函数
- 第四节:MVC中AOP思想的体现(四种过滤器)并结合项目案例说明过滤器的实际用法
- 【C++】基于C++的封装和运算符重载的思想,实现基于通讯录类的数据查询工作
- Java经典封装JDBC模板(充分体现面向对象思想)(转)
- Java经典封装JDBC模板(充分体现面向对象思想)
- 组件化思想之图片加载库picasso的用法及封装
- 一种基于简单递归思想的易操控xml解析封装(C++)
- Java经典封装JDBC模板(充分体现面向对象思想)
- Java经典封装JDBC模板(充分体现面向对象思想)
- C++定时器用法(已经封装成类)
- IOS 封装功能和逻辑思想
- C++面试题:举例说明set的用法。
- JDBC(五)面向对象编程思想和更新、查询封装
- vc 热键、组合键的用法 MFC c++ hotkey WM_HOTKEY
- [置顶] 无名管道的C++封装
- [C/C++]#ifndef,#define用法