回 帖 发 新 帖 刷新版面

主题:C语言中用结构实现位段--个人心血!值得一看哦!

C语言中的结构是有实现位段的能力的,噢!你问它到底是什么形式是吧?这个问题呆会给你答案。让我们先看看位段的作用:位段是在字段的声明后面加一个冒号以及一个表示字段位长的整数来实现的。这种用法又被就叫作“深入逻辑元件的编程”,如果你对系统编程感兴趣,那么这篇文章你就不应该错过!
  我把使用位段的几个理由告诉大家:1、它能把长度为奇数的数据包装在一起,从而节省存储的空间;2、它可以很方便地访问一个整型值的部分内容。
  首先我要提醒大家注意几点:1、位段成员只有三种类型:int ,unsigned int 和signed int这三种(当然了,int型位段是不是可以取负数不是我说了算的,因为这是和你的编译器来决定的。位段,位段,它是用来表示字段位长(bit)的,它只有整型值,不会有7.2这种float类型的,如果你说有,那你就等于承认了有7.2个人这个概念,当然也没有char这个类型的);2、成员名后面的一个冒号和一个整数,这个整数指定该位段的位长(bit);3、许多编译器把位段成员的字长限制在一个int的长度范围之内;4、位段成员在内存的实现是从左到右还是从右到左是由编译器来决定的,但二者皆对。
  下面我们就来看看,它到底是什么东西(我先假定大家的机器字长为32位):
  Struct WORD
  {
    unsigned int chara: 6:
    unsigned int font : 7;
    unsigned int maxsize : 19;
  };
  Struct WORD chone;
  这一段是从我编写的一个文字格式化软件摘下来的,它最多可以容纳64(既我说的unsigned int chara :6; 它总共是6位)个不同的字符值,可以处理128(既unsigned int font : 7 ;既2的7次方)种不同的字体,和2的19次方的单位长度的字。大家都可以看到maxsize是19位,它是无法被一个short int 类型的值所容纳的,我们又可以看到其余的成员的长度比char还小,这就让我们想起让他们共享32位机器字长,这就避免用一个32位的整数来表示maxsize的位段。怎么样?还要注意的是刚才的那一段代码在16位字长的机器上是无法实现的,为什么?提醒你一下,看看上面提醒的第3点,你会明白的!
你是不是发现这个东西没有用啊?如果你点头了,那你就错了!这么伟大的创造怎么会没有用呢(你对系统编程不感兴趣,相信你会改变这么一个观点的)?磁盘控制器大家应该知道吧?软驱与它的通信我们来看看是怎么实现的下面是一个磁盘控制器的寄存器:
      │←5→│←5→│←9→│←8→│←1→│←1→∣←1→∣←1→∣←1→∣
  上面位段从左到右依次代表的含义为:5位的命令,5位的扇区,9位的磁道,8位的错误代码,1位的HEAD LOADED,1位的写保护,1位的DISK SPINNING,1位的错误判断符,还有1位的READY位。它要怎么来实现呢?你先自己写写看:
  struct DISK_FORMAT
  {
       unsigned int command : 5;
     unsigned     sector  : 5;
       unsigned      track    :  9 ;
       unsigned      err_code  :  8;
       unsigned       ishead_loaded  :  1;
       unsigned      iswrit_protect   :  1;
        unsigned      isdisk_spinning  :  1;
       unsigned      iserr_ocur  : 1;
       undigned      isready    :1 ;
  };          
  注:代码中除了第一行使用了unsigned int 来声明位段后就省去了int ,这是可行的,详见ANCI C标准。
  如果我们要对044c18bfH的地址进行访问的话,那就这样:
  #define  DISK  ((struct DISK_FORMAT *)0x044c18bf)
  DISK->sector=fst_sector;
  DISK->track=fst_track;
  DISK->command=WRITE;
  当然那些都是要宏定义的哦!
  我们用位段来实现这一目的是很方便的,其实这也可以用移位或屏蔽来实现,你尝试过就知道哪个更方便了!
  我们今天的话题就到这儿,如果诸位还有疑问,可e-mail给我:arhuwen@163.com;
  特别声明哦:不要把以上内容用于不法行为,否则后果自负。另外本文不可用于任何谋取商业利益的举动,否则同上!
                                                                        -------Jeafos W.Yeh

回复列表 (共6个回复)

沙发

我的看法就是节省存储空间。是不是能提高程序的运行效率请指教。[em18]

板凳

我想你对这个问题是作了研究的,我的最主要的目的就是来节省系统运行时所占用的内存空间,但是不知你考虑过没有?这也是可以来节省时间的啊!
 用结构来实现,用指向运算符来进行访问是一种快捷的方式.如果位段还是那样长,那么程序在寻址时必定要计算地址和偏移地址之和,加法运算是要占用一定时间的,然后再寻址,再访问再返回;而指针只要去取址,再访问,再返回(开始的地址空间是由系统分配好的),是不是快了呢?希望我已经回答了你的问题!
  谢谢你的支持,我会更加努力,写出一些好文章的!谢谢!

3 楼

我虽然不了解c编译器内部是怎么处理你的这样一个结构!
但是在8086cup指令中,应该是没有从一 个字中间取出几个bit存放到寄存器中的指令的吧(当然后来的cpu是否增加了这么个指令我不清楚),而那几个bit操作的指令如:
bt btr bts 等指令,都只能对源数据中某一位进行读取操作,也就是说,c编译器,最终处理你这么个结构的话,也必然是模拟处理,因为cpu寻址最小单位为字节,根本不可能寻址到一个字的某一个bit位,而你的DISK->sector这样一个指针形式,是指向一个字的第N bit位,所以内部处理的话,应该是先将这个字用上述的位操作指令等相关指令将其中用户想要访问的位一bit一bit的读取存放于一个临时积存器或者内存地址中,然后在把这个积存器或内存地址中的值返回给用户,当然内部处理并不一定是说的这样,方法还有其他的,但是有一个是肯定,必然要用到临时存放读取的位数据,所以,我认为,楼主的这个方法,除了对bit操作有点方便外,并没有你所说的速度加快,相反,比直接用 ^ & |的位操作速度还要慢,因为就算c编译器内部就是调用位操作指令 xor or and等来处理的,那它还至少多了个指针寻址,所以速度会比直接进行位操作速度慢点!

4 楼

这个...是最基本的东西。n年以前就看到过...

5 楼

pentium4正解。这个东西的速度的确很慢,而且不只慢一点。懂一点汇编就会知道。

如果不是对硬件进行数据传输,或者内存是在是太紧张,这个方法不值得提倡。

6 楼

我想对firstrose说一句话,那就是你n年前就看到了,不等于别人就懂n年前就看到了,做为一个科学工作者,不应该有这么一种傲气,不应有浮躁的内心!!我可以断言,你没有前途!!!我这篇文章不是写给你看的!我下面问你一些问题:你会进行系统编程吗?或者说你精通吗?你会其他的一些深层次的编程吗?你问一下自己,有没有什么值得你骄傲的!
我还想对cybergate说一句,你看我的文章时看漏了一句,那就是:“如果你对系统编程感兴趣,那么这篇文章你就不应该错过!”你想象一下:如果在一个系统里面有几百几千个这样的语句,那么我们是多么愉快的省出了很大的空间可供用户使用啊!相信你应该明白!

我来回复

您尚未登录,请登录后再回复。点此登录或注册