C声明变量的用法体现C++封装思想

来源:互联网 发布:考驾照模拟软件 编辑:程序博客网 时间:2024/05/29 18:43

 

在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"myprintf.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个字节的空间,并把第一个字节空间的地址当成存储指针变量本身的空间地址;当声明一个其他类型变量(如整

型变量,结构体变量)时,编译器会计算整型或结构体所占空间大小,并分配出的类型大小的空间,同样把第一个字节空间的

地址当成存储此变量本身的空间地址。呵呵,有点绕口。。。 

原创粉丝点击