精华内容
下载资源
问答
  • 对于C语言来说,这没什么,定义一个联合体就行了,但是对于java来说,就有点晕了,因为平常我们用到的最小的是byte,要这样操作bit的话,我们需要一大堆运算,想想就很可怕。虽然可以用C写,然后用JNI调用,但是...

            本人android码农一个,这几天需要对接一个服务器,使用的是GTP协议,看了一下协议,顿时觉得蒙逼了。因为存储数据节约到了bit位,作为用惯了JAVA的人,顿时觉得这是得有多抠啊,不过由于我跟服务器用的是长连接,数据交互很频繁,所以这样其实大大节省了数据量,对于使用GPRS流量的用户是很有必要的。

            对接中我遇到的第一个问题就是数据封装和解析都是按bit位算的,一个数据占多少个bit这样的。现在遇到的问题就比如说,现在用两个byte来存CTRL,三个bit用来存版本号,一个bit用来做判断是否需要ACK,三个bit用来存优先级,9个bit用来存报文序号。对于C语言来说,这没什么,定义一个联合体就行了,但是对于java来说,就有点晕了,因为平常我们用到的最小的是byte,要这样操作bit位的话,我们需要一大堆位运算,想想就很可怕。虽然可以用C写,然后用JNI调用,但是不甘心我的还是想用java来更简单得实现。终于在洗澡的时候让我想到了,用string来实现。

           先说说原理,就是把一个string对象当成一块内存,里面存着一串bit,然后对里面的bit进行操作,最后再把这堆bit封装成byte。

           现在就以  用两个byte来存CTRL,三个bit用来存版本号,一个bit用来做判断是否需要ACK,三个bit用来存优先级,9个bit用来存报文序号   这个需求来实现吧。

          1、先封装三个方法一个是把int转成String格式的bit串,一个是string格式的bit串转为byte,一个是设定好bit串长度 。

     

    /** 
         * 将byte转成string格式bit串并省略前面的0
         */  
        public static String byteToBitFS(byte b) {  
        	boolean hn = false;
        	byte[] bits = new byte[8];
        	bits[0] = (byte)((b >> 7) & 0x1);
        	bits[1] = (byte)((b >> 6) & 0x1);
        	bits[2] = (byte)((b >> 5) & 0x1);
        	bits[3] = (byte)((b >> 4) & 0x1);
        	bits[4] = (byte)((b >> 3) & 0x1);
        	bits[5] = (byte)((b >> 2) & 0x1);
        	bits[6] = (byte)((b >> 1) & 0x1);
        	bits[7] = (byte)((b >> 0) & 0x1);
        	StringBuffer sb = new StringBuffer();
        	for(byte temp : bits){
        		if(hn){
        			sb.append(temp);	
        		}else{
        			if(temp != 0x00){
        				sb.append(temp);	
        				hn=true;
            			
            		}
        		}
        		
        	}
        	
            return sb.toString();  
        } 
        
        /** 
         * 将string格式的bit串转成byte 
         */  
        public static byte BitToByte(String byteStr) {  
            int re, len;  
            if (null == byteStr) {  
                return 0;  
            }  
            len = byteStr.length();  
            if (len != 4 && len != 8) {  
                return 0;  
            }  
            if (len == 8) { 
                if (byteStr.charAt(0) == '0') {
                    re = Integer.parseInt(byteStr, 2);  
                } else {
                    re = Integer.parseInt(byteStr, 2) - 256;  
                }  
            } else {
                re = Integer.parseInt(byteStr, 2);  
            }  
            return (byte) re;  
        }  
    /**
    	 * 检查bit是长度是否足够,不够前面添0,超出返回null
    	 */
    	public static String resetBitStrand(String str, int length) {
    		if (str.length() > length) {
    			return null;
    		}
    		StringBuffer sb = new StringBuffer();
    		if (str.length() < length) {
    			for (int i = 0; i < length - str.length(); i++) {
    				sb.append("0");
    			}
    		}
    		sb.append(str);
    		return sb.toString();
    
    
    	}
    	 * 检查bit是长度是否足够,不够前面添0,超出返回null
    	 */
    	public static String resetBitStrand(String str, int length) {
    		if (str.length() > length) {
    			return null;
    		}
    		StringBuffer sb = new StringBuffer();
    		if (str.length() < length) {
    			for (int i = 0; i < length - str.length(); i++) {
    				sb.append("0");
    			}
    		}
    		sb.append(str);
    		return sb.toString();
    
    
    	}
    

         2、先把2个byte也就是16个bit的位置准备好,开始添加数据

     

     

    public static void setCTRL(byte version, boolean needack, byte priority,
    			int sno) {
    		StringBuffer sb = new StringBuffer();
    		// 添加版本号
    		String ver = resetBitStrand(byteToBitFS(version), 3);
    		sb.append(ver);
    		// 添加是否需要ack
    		sb.append(needack ? 1 : 0);
    		// 添加优先级
    		String str_priority = resetBitStrand(byteToBitFS(priority), 3);
    		sb.append(str_priority);
    		// 添加包序号
    		String str_sno = resetBitStrand(Integer.toBinaryString(sno), 9);
    		sb.append(str_sno);
    		
    		//最后封装完成的bit串
    		String bitStand = sb.toString();
    		
    		//将bit串转为byte
    		byte b1 = BitToByte(bitStand.substring(0,8));
    		byte b2 = BitToByte(bitStand.substring(8,16));
    		System.out.println("最后的结果bit串: "+bitStand+"    两个byte:"+b1+"-"+b2);
    
    	}


               到这里就封装就大功告成啦,解析反其道而行就行啦,我就不再多说了。

     

               这种实现方法不是唯一的,也不是最好的,但是也提供了一个例子.

              

     

     

    展开全文
  • 在工程中图方便 定义了枚举变量和联合体来简化操作 代码如下: ``` typedef enum{ MODE0=0x01, MODE1=0x02, MODE2=0x04, MODE3=0x08, MODE4=0x10, }MODEx_e; typedef union{ MODEx_e bytes; ...
  • 联合体和位域的基本概念参考互联网,这种做法适合进行用在硬件寄存器操作的和通信协议栈管理上,可以很大程度的提高程序的可靠性和可阅读性。例如将单片机的每个寄存器定义成这种方式之后就可以使用运算符“.”对...

    联合体和位域的基本概念参考互联网,这种做法适合进行用在硬件寄存器操作的和通信协议栈管理上,可以很大程度的提高程序的可靠性和可阅读性。例如将单片机的每个寄存器定义成这种方式之后就可以使用运算符“.”对寄存器进行操作而不是使用易错难懂的类似“reg1 &= ~(1 << 8);”的与或操作(位带操作)。详细见下面的测试程序。

    #include "stdio.h"
    
    union test
    {
        struct bit_feild
        {
            char bit0:1;
            char bit1:1;
            char bit2:1;
            char bit3:1;
            char bit4:1;
            char bit5:1;
            char bit6:1;
            char bit7:1;
        } bits;
        unsigned char data;
    };
    
    int main()
    {
        union test t;
        printf("%d,%d,%d,\r\n",(int)sizeof(t),t.data,t.bits.bit0);
    
        //1操作
        t.bits.bit0 = 1;
        printf("%d,%d,%d,\r\n",(int)sizeof(t),t.data,t.bits.bit0);
    
        t.bits.bit1 = 1;
        printf("%d,%d,%d,\r\n",(int)sizeof(t),t.data,t.bits.bit1);
    
        t.bits.bit2 = 1;
        printf("%d,%d,%d,\r\n",(int)sizeof(t),t.data,t.bits.bit2);
    
        t.bits.bit3 = 1;
        printf("%d,%d,%d,\r\n",(int)sizeof(t),t.data,t.bits.bit3);
    
        t.bits.bit4 = 1;
        printf("%d,%d,%d,\r\n",(int)sizeof(t),t.data,t.bits.bit4);
    
        t.bits.bit5 = 1;
        printf("%d,%d,%d,\r\n",(int)sizeof(t),t.data,t.bits.bit5);
    
        t.bits.bit6 = 1;
        printf("%d,%d,%d,\r\n",(int)sizeof(t),t.data,t.bits.bit6);
    
        t.bits.bit7 = 1;
        printf("%d,%d,%d,\r\n",(int)sizeof(t),t.data,t.bits.bit7);
    
    
        printf("\r\n\r\n");
    
    
        //判断位,位读取操作读出来的数据如果是1得到的是0xFFFFFFFF,如果是0得到的是0
        if(t.bits.bit7)
            printf("bit7 is 1\r\n");
        else
            printf("bit7 is 0\r\n");
    
    
        printf("\r\n\r\n");
    
    
        //0操作
        t.bits.bit0 = 0;
        printf("%d,%d,%d,\r\n",(int)sizeof(t),t.data,t.bits.bit0);
    
        t.bits.bit1 = 0;
        printf("%d,%d,%d,\r\n",(int)sizeof(t),t.data,t.bits.bit1);
    
        t.bits.bit2 = 0;
        printf("%d,%d,%d,\r\n",(int)sizeof(t),t.data,t.bits.bit2);
    
        t.bits.bit3 = 0;
        printf("%d,%d,%d,\r\n",(int)sizeof(t),t.data,t.bits.bit3);
    
        t.bits.bit4 = 0;
        printf("%d,%d,%d,\r\n",(int)sizeof(t),t.data,t.bits.bit4);
    
        t.bits.bit5 = 0;
        printf("%d,%d,%d,\r\n",(int)sizeof(t),t.data,t.bits.bit5);
    
        t.bits.bit6 = 0;
        printf("%d,%d,%d,\r\n",(int)sizeof(t),t.data,t.bits.bit6);
    
        t.bits.bit7 = 0;
        printf("%d,%d,%d,\r\n",(int)sizeof(t),t.data,t.bits.bit7);
    
    
        printf("\r\n\r\n");
    
    
        //判断位,位读取操作读出来的数据如果是1得到的是0xFFFFFFFF,如果是0得到的是0
        if(t.bits.bit7)
            printf("bit7 is 1\r\n");
        else
            printf("bit7 is 0\r\n");
    
        return 0;
    }
    展开全文
  •  段(bit-field)是以为单位来定义结构体(或联合体)中的成员变量所占的空间。含有段的结构体(联合体)称为段结构。采用段结构既能够节省空间,又方便于操作。  段的定义格式为:  type [var]: digits  ...
  • 编程中,需要使用到union联合体,不清楚到底...发现bit按照定义定义在前的为实际的低位 #include typedef unsigned long u32; typedef unsigned short u16; typedef struct { // bits description u16 DI0:

    编程中,需要使用到union联合体,不清楚到底在内存中是怎么对应的,所以写了个测试的函数,进行测试了下。发现bit位按照定义,定义在前的为实际的低位

    #include <stdio.h>
    
    typedef unsigned long  u32;
    typedef unsigned short u16;
    
    typedef struct  {      // bits description
       u16 DI0:1;          // 0    
       u16 DI1:1;          // 1    
       u16 DI2:1;          // 2    
       u16 DI3:1;          // 3    
       u16 DI4:1;          // 4    
       u16 DI5:1;          // 5  
       u16 DI6:1;          // 6   
       u16 DI7:1;          // 7
       u16 DI8:1;          // 8    
       u16 DI9:1;          // 9    
       u16 DI10:1;         // 10    
       u16 DI11:1;         // 11  
       u16 DI12:1;         // 12   
       u16 DI13:1;         // 13
                 
       u16 rsvd:2;     // 15:14 reserved
    }DIREG_BITS;
    
    typedef union  {
       u16  all;
       DIREG_BITS  	bit;
    }DI_REG;
    
    int main()
    {
    	DI_REG di_reg;
        di_reg.bit.DI0 = 1;
        di_reg.bit.DI1 = 0;
        di_reg.bit.DI2 = 0;
        di_reg.bit.DI3 = 0;
        di_reg.bit.DI4 = 0;
        di_reg.bit.DI5 = 0;
        di_reg.bit.DI6 = 0;
        di_reg.bit.DI7 = 0;
        di_reg.bit.DI8 = 0;
        di_reg.bit.DI9 = 0;
        di_reg.bit.DI10 = 0;
        di_reg.bit.DI11 = 1;
        di_reg.bit.DI12 = 1;
        di_reg.bit.DI13 = 1;
        printf("di_reg.all = %d\n",di_reg.all);
    	sleep(50000);
    	return 0;
    }
    

    测试结果:打印结果为14437



    10进制14337转换为2进制为:11100000000001。

    至此解决了,在编程过程中的顺序对应问题。


    展开全文
  • c语言位

    2015-08-02 12:39:52
    段(bit-field)是以为单位来定义结构体(或联合体)中的成员变量所占的空间。含有段的结构体(联合体)称为段结构。采用段结构既能够节省空间,又方便于操作。段的定义格式为: type [var]: digits其中type...
    通常计算机最小处理单元基本就是byte字节了,就是八个二进制位,位段则是按计算机中真正的最小单位二进制位来存储处理数据,可以更高效的利用内存。

    位段(bit-field)是以位为单位来定义结构体(或联合体)中的成员变量所占的空间。含有位段的结构体(联合体)称为位段结构。采用位段结构既能够节省空间,又方便于操作。

    位段的定义格式为: type  [var]: digits

    其中type只能为int,unsigned int,signed int三种类型(int型能不能表示负数视编译器而定,比如VC中int就默认是signed int,能够表示负数)。位段名称var是可选参数,即可以省略。digits表示该位段所占的二进制位数。

     那么定义一个位段结构可以像下面这段代码去定义:

    struct node
    {
    unsigned int a:4; //位段a,占4位
    unsigned int :0; //无名位段,占0位定义长度为0的位段时不能指定名字,否则编译不过)(下一个位段从下一个位段存储单元开始存放)
        unsigned int b:4;     //位段b,占4位
        int c:32;             //位段c,占32位(位段占的二进制位数不能超过该基本类型所能表示的最大位数)( 一个位段必须存储在同一个存储单元中,不能跨两个单元.如果某存储单元空间中不能容纳下一个位段,则该空间不用,而从下一个存储单元起存放该位段
        int  :6;              //无名位段,占6位无名位段不能被访问,但是会占据空间)
    };

    一.位段的使用

        使用位段需注意一下几点:

        1)位段的类型只能是int,unsigned int,signed int三种类型,不能是char型或者浮点型;

        2)位段占的二进制位数不能超过该基本类型所能表示的最大位数,比如在VC中int是占4个字节,那么最多只能是32位

        3)无名位段不能被访问,但是会占据空间;

        4)不能对位段进行取地址操作;

        5)若位段占的二进制位数为0,则这个位段必须是无名位段,下一个位段从下一个位段存储单元(这里的位段存储单元经测试在VC环境下是4个字节)开始存放;

        6)若位段出现在表达式中,则会自动进行整型升级,自动转换为int型或者unsigned int。

        7)对位段赋值时,最好不要超过位段所能表示的最大范围,否则可能会造成意想不到的结果。

        8)位段不能出现数组的形式。

    二.位段结构在内存中的存储方式

        对于位段结构,编译器会自动进行存储空间的优化,主要有这几条原则:

       1)如果一个位段存储单元能够存储得下位段结构中的所有成员,那么位段结构中的所有成员只能放在一个位段存储单元中,不能放在两个位段存储单元中;如果一个位段存储单元不能容纳下位段结构中的所有成员,那么从剩余的位段从下一个位段存储单元开始存放。(在VC中位段存储单元的大小是4字节).

       2)如果一个位段结构中只有一个占有0位的无名位段,则只占1或0字节的空间(C语言中是占0字节,而C++中占1字节);否则其他任何情况下,一个位段结构所占的空间至少是一个位段存储单元的大小;

    展开全文
  • 关于结构体,段,枚举,联合体的总结 1.结构体 (1)结构体变量的定义和初始化 struct Point { int x; int y; }p1; //声明类型的同时定义变量 p1 struct Point p2; //定义结构体变量p2 //初始化:定义变量的...
  • C语言位段问题

    2014-08-07 01:09:51
     段(bit-field)是以为单位来定义结构体(或联合体)中的成员变量所占的空间。含有段的结构体(联合体)称为段结构。采用段结构既能够节省空间,又方便于操作。  段的定义格式为:  type [var]: ...
  • 清华大学黄维通设计制作 清华大学黄维通设计制作 PAGE ...结构体指针 结构体在函数间的传递 结构体指针型和结构体型函数 结构体嵌套 联合体 枚举类型 自定义类型 字段结构体 8.1结构体的说明和定义 8.1.1什么叫结构体
  • C语言位段结构

    2018-03-14 11:31:45
    段(bit-field)是以为单位来定义结构体(或联合体)中的成员变量所占的空间。含有段的结构体(联合体)称为段结构。采用段结构既能够节省空间,又方便于操作。 段的定义格式为: type [var]:digits 其中...
  • C语言中的

    2018-05-02 21:23:46
    段(bit-field)是以为单位来定义结构体(或联合体)中的成员变量所占的空间。含有段的结构体(联合体)称为段结构。采用段结构既能够节省空间,又方便于操作。 段的定义格式为: 类型 成员名: 占用数目 ...
  • 浅谈c语言中的

    2017-08-14 00:35:25
     段(bit-field)是以为单位来定义结构体(或联合体)中的成员变量所占的空间。含有段的结构体(联合体)称为段结构。采用段结构既能够节省空间,又方便于操作。  段的定义格式为:  type [var]: digits ...
  • 浅谈C语言中的

    2016-01-08 23:46:00
    段(bit-field)是以为单位来定义结构体(或联合体)中的成员变量所占的空间。含有段的结构体(联合体)称为段结构。采用段结构既能够节省空间,又方便于操作。 段的定义格式为: type [var]:digits 其中...
  • /* 本例程是C语言的位域操作示例 这里为什么位域结构体与联合体一起使用? -->因为这样定义后,即可以单独使用标志 也可同时...//====标志应用 定义联合体实体==== typedef union uFLG { uint8 Flg ; ...
  • 浅谈C语言位

    2013-02-20 13:39:37
    段(bit-field)是以为单位来定义结构体(或联合体)中的成员变量所占的空间。含有段的结构体(联合体)称为段结构。采用段结构既能够节省空间,又方便于操作。  段的定义格式为:  type [var]: ...
  • 段(bit-field)是以为单位来定义结构体(或联合体)中的成员变量所占的空间。含有段的结构体(联合体)称为段结构。采用段结构既能够节省空间,又方便于操作。 段的定义格式为: type [var]:digits 其中...
  • 目录 1. C 语言中的指针和内存泄漏 5 2. C语言难点分析整理 10 3. C语言难点 18 4. C/C++实现冒泡排序算法 32 5. C++中指针和引用的区别 35 6. const char*, char const*, char*const的区别 ...85. C语言常用宏定义 450
  • iOS运算及联合体位域

    千次阅读 2020-10-02 21:47:43
    目录1. 概述2. 运算2.1 按与运算2.2 按或运算2.3 按异或运算2.4 取反运算2.5 左移...在C语言中共提供了6中运算符,具体如下: & 按与 | 按或 ^ 按异或 ~ 取反 << 左移 >> 右移

空空如也

空空如也

1 2 3 4
收藏数 63
精华内容 25
关键字:

c语言联合体位定义

c语言 订阅