如何查看位域成员的地址

大飞的江湖 2014-05-16 03:48:53
现在有一个结构体
struct data
{
unsigned int num1 :1;
unsigned int num2 :3;
char num3 :4;
unsigned int :0;
unsigned int num4:6;
}
有什么办法可以查看各个成员变量的地址?求教?还望高手指点
...全文
687 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
大飞的江湖 2014-05-20
  • 打赏
  • 举报
回复
引用 10 楼 zhao4zhong1 的回复:
仅供参考
#include <stdio.h>
#pragma pack(push,1)
union U {
    unsigned char byte;
    struct BF {
        unsigned int b0:1;//a
        unsigned int b1:1;//b
        unsigned int b2:1;//c
    } bf;
} u;
#pragma pack(pop)
unsigned char bt;
int a,b,c;
int main() {
    for (bt=0;bt<8;bt++) {
        u.byte=(unsigned char)bt;
        a=u.bf.b0;
        b=u.bf.b1;
        c=u.bf.b2;
        printf("byte 0x%02x -- c:%d b:%d a:%d\n",bt,c,b,a);
    }
    for (c=0;c<2;c++)
    for (b=0;b<2;b++)
    for (a=0;a<2;a++) {
        u.bf.b0=a;
        u.bf.b1=b;
        u.bf.b2=c;
        bt=u.byte;
        printf("c:%d b:%d a:%d -- byte 0x%02x\n",c,b,a,bt);
    }
    return 0;
}
//byte 0x00 -- c:0 b:0 a:0
//byte 0x01 -- c:0 b:0 a:1
//byte 0x02 -- c:0 b:1 a:0
//byte 0x03 -- c:0 b:1 a:1
//byte 0x04 -- c:1 b:0 a:0
//byte 0x05 -- c:1 b:0 a:1
//byte 0x06 -- c:1 b:1 a:0
//byte 0x07 -- c:1 b:1 a:1
//c:0 b:0 a:0 -- byte 0x00
//c:0 b:0 a:1 -- byte 0x01
//c:0 b:1 a:0 -- byte 0x02
//c:0 b:1 a:1 -- byte 0x03
//c:1 b:0 a:0 -- byte 0x04
//c:1 b:0 a:1 -- byte 0x05
//c:1 b:1 a:0 -- byte 0x06
//c:1 b:1 a:1 -- byte 0x07

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
    float f;
    double d;
    char bs[65];
    char b[65];
    char s[80];
    unsigned char *p;
    char e[12];
    char *t;
    int ex;

    while (1) {
        printf("Input a float point number:");fflush(stdout);
        rewind(stdin);
        fgets(s,80,stdin);
        if (1==sscanf(s,"%f",&f) && 1==sscanf(s,"%lf",&d)) break;
    }
    printf("f=%g\n",f);
    p=(unsigned char *)&f;
    printf("hex=%02X %02X %02X %02X\n",p[3],p[2],p[1],p[0]);
    ltoa(*(long *)&f,b,2);
    sprintf(bs,"%032s",b);
    printf("bin=%s\n",bs);
    printf("bin=%.1s %.8s   %s\n",bs,bs+1,bs+9);
    strncpy(e,bs+1,8);e[8]=0;
    ex=strtol(e,&t,2);
    printf("    %c %-4d-127 1.%s\n",(bs[0]=='0')?'+':'-',ex,bs+9);
    ex-=127;
    printf("    %c %-8d 1.%s\n",(bs[0]=='0')?'+':'-',ex,bs+9);

    printf("\nd=%lg\n",d);
    p=(unsigned char *)&d;
    printf("hex=%02X %02X %02X %02X %02X %02X %02X %02X\n",p[7],p[6],p[5],p[4],p[3],p[2],p[1],p[0]);
    _i64toa(*(__int64 *)&d,b,2);
    sprintf(bs,"%064s",b);
    printf("bin=%s\n",bs);
    printf("bin=%.1s %.11s   %s\n",bs,bs+1,bs+12);
    strncpy(e,bs+1,11);e[11]=0;
    ex=strtol(e,&t,2);
    printf("    %c %-6d-1023 1.%s\n",(bs[0]=='0')?'+':'-',ex,bs+12);
    ex-=1023;
    printf("    %c %-11d 1.%s\n",(bs[0]=='0')?'+':'-',ex,bs+12);

    return 0;
}
//Input a float point number:0.125
//f=0.125
//hex=3E 00 00 00
//bin=00111110000000000000000000000000
//bin=0 01111100   00000000000000000000000
//    + 124 -127 1.00000000000000000000000
//    + -3       1.00000000000000000000000
//
//d=0.125
//hex=3F C0 00 00 00 00 00 00
//bin=0011111111000000000000000000000000000000000000000000000000000000
//bin=0 01111111100   0000000000000000000000000000000000000000000000000000
//    + 1020  -1023 1.0000000000000000000000000000000000000000000000000000
//    + -3          1.0000000000000000000000000000000000000000000000000000
//
多谢 多谢 例子很好
richyhuang 2014-05-19
  • 打赏
  • 举报
回复
引用 9 楼 yang382197207 的回复:
[quote=引用 6 楼 richyhuang 的回复:] bit field是一种压缩的数据类型,其元素不一定以8为倍数的,所以只能看到整个结构的地址,而不能指定某一个元素的地址
可事实上有时候会想看一下,位域的排列,对齐,数据是都压缩存储,这个可以通过什么来查看?内存吗[/quote] 用watch试试吧,
赵4老师 2014-05-19
  • 打赏
  • 举报
回复
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
int main() {
    int i,v;
    char bs[33];
    char b[33];
    char hs[9];
    char h[9];
    char s[4];
    char *e;

// 十进制整数转二进制串;
    i=1024;
    ltoa(i,b,2);
    sprintf(bs,"%032s",b);
    printf("i=%d,bs=%s\n",i,bs);
// 十进制整数转十六进制串;
    i=1024;
    ltoa(i,h,16);
    sprintf(hs,"%08s",h);
    printf("i=%d,hs=%s\n",i,hs);
// 十六进制字符串转成十进制数
    strcpy(hs,"00000400");
    sscanf(hs,"%x",&i);
    printf("hs=%s,i=%d\n",hs,i);
// 二进制字符串转化为十六进制字符串;
    strcpy(bs,"00000000000000000000010000000000");
    i=strtol(bs,&e,2);
    ltoa(i,h,16);
    sprintf(hs,"%08s",h);
    printf("bs=%s,hs=%s\n",bs,hs);
// 二进制字符串转化为十进制数;
    strcpy(bs,"00000000000000000000010000000000");
    i=strtol(bs,&e,2);
    printf("bs=%s,i=%d\n",bs,i);
// 十六进制字符串转成二进制串
    strcpy(hs,"00000400");
    sscanf(hs,"%x",&i);
    ltoa(i,b,2);
    sprintf(bs,"%032s",b);
    printf("hs=%s,bs=%s\n",hs,bs);
// ASC\GBK字符串转十六进制串
    strcpy(s,"a汉");
    i=0;
    while (1) {
        if (0==s[i]) break;
        sprintf(hs+i*2,"%02X",(unsigned char)s[i]);
        i++;
    }
    setlocale(LC_ALL,"chs");
    printf("s=%s,hs=%s\n",s,hs);
// 十六进制字符串转成汉字(GBK)及字符(ASC)
    strcpy(hs,"61BABA");
    i=0;
    while (1) {
        if (1!=sscanf(hs+i*2,"%2x",&v)) break;
        s[i]=(char)v;
        i++;
    }
    s[i]=0;
    printf("hs=%s,s=%s\n",hs,s);

    return 0;

}
//i=1024,bs=00000000000000000000010000000000
//i=1024,hs=00000400
//hs=00000400,i=1024
//bs=00000000000000000000010000000000,hs=00000400
//bs=00000000000000000000010000000000,i=1024
//hs=00000400,bs=00000000000000000000010000000000
//s=a汉,hs=61BABA
//hs=61BABA,s=a汉
赵4老师 2014-05-19
  • 打赏
  • 举报
回复
仅供参考
#include <stdio.h>
#pragma pack(push,1)
union U {
    unsigned char byte;
    struct BF {
        unsigned int b0:1;//a
        unsigned int b1:1;//b
        unsigned int b2:1;//c
    } bf;
} u;
#pragma pack(pop)
unsigned char bt;
int a,b,c;
int main() {
    for (bt=0;bt<8;bt++) {
        u.byte=(unsigned char)bt;
        a=u.bf.b0;
        b=u.bf.b1;
        c=u.bf.b2;
        printf("byte 0x%02x -- c:%d b:%d a:%d\n",bt,c,b,a);
    }
    for (c=0;c<2;c++)
    for (b=0;b<2;b++)
    for (a=0;a<2;a++) {
        u.bf.b0=a;
        u.bf.b1=b;
        u.bf.b2=c;
        bt=u.byte;
        printf("c:%d b:%d a:%d -- byte 0x%02x\n",c,b,a,bt);
    }
    return 0;
}
//byte 0x00 -- c:0 b:0 a:0
//byte 0x01 -- c:0 b:0 a:1
//byte 0x02 -- c:0 b:1 a:0
//byte 0x03 -- c:0 b:1 a:1
//byte 0x04 -- c:1 b:0 a:0
//byte 0x05 -- c:1 b:0 a:1
//byte 0x06 -- c:1 b:1 a:0
//byte 0x07 -- c:1 b:1 a:1
//c:0 b:0 a:0 -- byte 0x00
//c:0 b:0 a:1 -- byte 0x01
//c:0 b:1 a:0 -- byte 0x02
//c:0 b:1 a:1 -- byte 0x03
//c:1 b:0 a:0 -- byte 0x04
//c:1 b:0 a:1 -- byte 0x05
//c:1 b:1 a:0 -- byte 0x06
//c:1 b:1 a:1 -- byte 0x07

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
    float f;
    double d;
    char bs[65];
    char b[65];
    char s[80];
    unsigned char *p;
    char e[12];
    char *t;
    int ex;

    while (1) {
        printf("Input a float point number:");fflush(stdout);
        rewind(stdin);
        fgets(s,80,stdin);
        if (1==sscanf(s,"%f",&f) && 1==sscanf(s,"%lf",&d)) break;
    }
    printf("f=%g\n",f);
    p=(unsigned char *)&f;
    printf("hex=%02X %02X %02X %02X\n",p[3],p[2],p[1],p[0]);
    ltoa(*(long *)&f,b,2);
    sprintf(bs,"%032s",b);
    printf("bin=%s\n",bs);
    printf("bin=%.1s %.8s   %s\n",bs,bs+1,bs+9);
    strncpy(e,bs+1,8);e[8]=0;
    ex=strtol(e,&t,2);
    printf("    %c %-4d-127 1.%s\n",(bs[0]=='0')?'+':'-',ex,bs+9);
    ex-=127;
    printf("    %c %-8d 1.%s\n",(bs[0]=='0')?'+':'-',ex,bs+9);

    printf("\nd=%lg\n",d);
    p=(unsigned char *)&d;
    printf("hex=%02X %02X %02X %02X %02X %02X %02X %02X\n",p[7],p[6],p[5],p[4],p[3],p[2],p[1],p[0]);
    _i64toa(*(__int64 *)&d,b,2);
    sprintf(bs,"%064s",b);
    printf("bin=%s\n",bs);
    printf("bin=%.1s %.11s   %s\n",bs,bs+1,bs+12);
    strncpy(e,bs+1,11);e[11]=0;
    ex=strtol(e,&t,2);
    printf("    %c %-6d-1023 1.%s\n",(bs[0]=='0')?'+':'-',ex,bs+12);
    ex-=1023;
    printf("    %c %-11d 1.%s\n",(bs[0]=='0')?'+':'-',ex,bs+12);

    return 0;
}
//Input a float point number:0.125
//f=0.125
//hex=3E 00 00 00
//bin=00111110000000000000000000000000
//bin=0 01111100   00000000000000000000000
//    + 124 -127 1.00000000000000000000000
//    + -3       1.00000000000000000000000
//
//d=0.125
//hex=3F C0 00 00 00 00 00 00
//bin=0011111111000000000000000000000000000000000000000000000000000000
//bin=0 01111111100   0000000000000000000000000000000000000000000000000000
//    + 1020  -1023 1.0000000000000000000000000000000000000000000000000000
//    + -3          1.0000000000000000000000000000000000000000000000000000
//
大飞的江湖 2014-05-19
  • 打赏
  • 举报
回复
引用 6 楼 richyhuang 的回复:
bit field是一种压缩的数据类型,其元素不一定以8为倍数的,所以只能看到整个结构的地址,而不能指定某一个元素的地址
可事实上有时候会想看一下,位域的排列,对齐,数据是都压缩存储,这个可以通过什么来查看?内存吗
大飞的江湖 2014-05-19
  • 打赏
  • 举报
回复
引用 4 楼 lm_whales 的回复:
位域无地址,但是可以看到位域变量占了哪些位; 方法是其他位为0,某位域变量全1 然后逐个字节,或者逐位输出。
这个方法不错,有用
大飞的江湖 2014-05-19
  • 打赏
  • 举报
回复
位域不能取地址的&
lm_whales 2014-05-17
  • 打赏
  • 举报
回复
位域无地址,但是可以看到位域变量占了哪些位; 方法是其他位为0,某位域变量全1 然后逐个字节,或者逐位输出。
lm_whales 2014-05-17
  • 打赏
  • 举报
回复
把他当成char 数组解释每个位即可
richyhuang 2014-05-17
  • 打赏
  • 举报
回复 2
bit field是一种压缩的数据类型,其元素不一定以8为倍数的,所以只能看到整个结构的地址,而不能指定某一个元素的地址
Morrisss_ 2014-05-17
  • 打赏
  • 举报
回复
引用 1 楼 zcdabing 的回复:

struct data
 {
       unsigned int  num1;
       unsigned int num2 ;
	   char ch1;
       unsigned int  num3;
       unsigned int num4;
 };

data a;
unsigned int *p_nNum1=&a.num1;
printf("%d ",p_nNum1,);

你写的这个都不是bit field。bit field不能取地址
zcdabing 2014-05-16
  • 打赏
  • 举报
回复
引用 1 楼 zcdabing 的回复:

struct data
 {
       unsigned int  num1;
       unsigned int num2 ;
	   char ch1;
       unsigned int  num3;
       unsigned int num4;
 };

data a;
unsigned int *p_nNum1=&a.num1;
printf("%d ",p_nNum1,);

这个是偏移量 参考下 [code=c][/ #include "stdafx.h" #include<stdio.h> struct data { unsigned int num1; unsigned int num2 ; char ch1; unsigned int num3; unsigned int num4; }; int main(int argc, char* argv[]) { data a; unsigned int data::*p_nNum1=&data::num1; unsigned int data::*p_nNum2=&data::num2; unsigned int data::*p_nNum3=&data::num3; unsigned int data::*p_nNum4=&data::num4; char data::*p_cCh1=&data::ch1; printf("%d %d %d %d %d",p_nNum1,p_nNum2,p_nNum3,p_nNum4,p_cCh1); return 0; }code]
zcdabing 2014-05-16
  • 打赏
  • 举报
回复

struct data
 {
       unsigned int  num1;
       unsigned int num2 ;
	   char ch1;
       unsigned int  num3;
       unsigned int num4;
 };

data a;
unsigned int *p_nNum1=&a.num1;
printf("%d ",p_nNum1,);

学习并掌握C++2.0(11+14+17+20)的新特性,学习线程及线程池的应用 ---------------------------------------------------给小白学员的3年学习路径及计划技术方面分三块:1.纯开发技术方向2.音视频流媒体专业方向3.项目实战---------------------------------------------------1.纯开发技术方向(1) C++必须要过硬(至少学会10本经典好书)(2) 系统级编程(Windows、Linux),必须特别熟练系统API,灵活运用(3) 框架与工具(Qt、MFC):必须精通其中一种。(4) 架构与设计模式:需要提升一个高度,不再是简单的编码,而是思维模式。(5) 驱动级别(如果有兴趣,可以深入到驱动级:包括Windows、Linux)(6) 最好学习点Java+Html+javascript等WEB技术。2.音视频流媒体专业方向(1) 音视频流媒体基础理论:   必须认真学会,否则看代码就是看天书(2) 编解码方向:精通h.264,h.265(hevc), 包括理论和各个开源库(ffmpeg,libx264,libx265,...)。(3) 直播方向:  精通各种直播协议(rtsp,rtmp,hls,http-flv,...), 钻研各个开源库(live555,darwin,srs,zlmediakit,crtmpserver,...)(4) 视频监控:  理论+开源库(onvif+281818)(EasyMonitor、iSpy、ZoneMinder(web)、...) 3.项目实战(1) Qt项目:  至少要亲手练习10个实战项目(网络服务器、多线程、数据库、图像处理、多人聊天、等等)(2)音视频项目:包括编解码、视频监控、直播等各个方向,都需要亲手实战项目,包括视频服务器、后台管理系统、前端播放器(多端)---------------------------------------------------  第1章 C++11新特性 41). nullptr关键字与新语法 42). auto和decltype类型推导 6 auto讲解 6 auto示例 7 decltype 83). for区间迭代 94). 初始化列表 105). 模板增强 11外部模板 11类型别名模板 12默认模板参数 126). 构造函数 13委托构造 13继承构造 147). Lambda 表达式 158). 新增容器 20std::array 20std::forward_list 21无序容器 22元组 std::tuple 239). 正则表达式 2610). 语言级线程支持 28多线程库简介 2811). 右值引用和move语义 31右值引用和move语义 32转移左值 3412). constexpr 35第2章 C++14新特性 36Lambda 函数 36类型推导 37返回值类型推导(Return type deduction) 37泛型lambda 39[[弃用的]]  [[deprecated]]属性 40二进制数字和数字分隔符 41第3章 C++17新特性 42安装GCC10.2 42安装msys2-x86_64-20200720 42更新镜像 42更新软件库 43安装 MinGW64 等必要的软件 43环境变量Path 43编译命令 43constexpr 44typename 45折叠表达式 47结构化绑定 48条件分支语句初始化 49聚合初始化 50嵌套命名空间 52lambda表达式捕获*this的值 53改写/继承构造函数 54用auto作为非类型模板参数 55__has_include 56fallthrough 57nodiscard 57maybe_unused 58第4章 C++20新特性 59编译命令 59concept 59typename 60explicit 61constinit 62位域变量的默认成员初始化 62指定初始化 63基于范围的for循环初始化 64放宽基于范围的for循环,新增自定义范围方法 65嵌套内联命名空间 66允许用圆括弧的值进行聚合初始化 67unicode字符串字面量 68允许转换成未知边界的数组 68likely和unlikely 69第5章 C++2.0(11/14/17/20)总结与分析 705.1 C语言与C++ 715.2 语言可用性的强化 725.2.1 常量 725.2.2 变量及其初始化 735.2.3 类型推导 745.2.4 控制流 765.2.5 模板 775.2.6 面向对象 815.3 语言运行期的强化 835.3.1 Lambda 表达式 835.3.2 右值引用 865.4 容器 885.4.1 线性容器 885.4.2 无序容器 895.4.3 元组 895.5 智能指针与内存管理 905.5.1 RAII 与引用计数 905.5.2 std::shared_ptr 905.5.3 std::unique_ptr 915.5.4 std::weak_ptr 91第6章 C++2.0多线程原理与实战 93什么是并发 93并发的方式 93为什么使用并发 95线程简介 96创建线程的三种方式 971. 通过函数 972.通过类对象创建线程 993.通过lambda表达式创建线程 101thread线程的使用 101互斥量与临界区 105期物Future 111条件变量 112原子操作 114内存模型 118第7章 C++2.0线程池原理与实战 120线程与线程池的基本原理 1201)、线程 1202)、线程的生命周期 1213)、什么是单线程和多线程 1214)、线程池 1225)、四种常见的线程池 123线程池的架构与流程 123线程池代码实战 125    
第八章:枚举,位运算 枚举   在实际问题中, 有些变量的取值被限定在一个有限的范围内。例如,一个星期内只有七天,一年只有十二个月, 一个班每周有六门课程等等。如果把这些量说明为整型, 字符型或其它类型显然是不妥当的。 为此,C语言提供了一种称为“枚举”的类型。在“枚举”类型的定义中列举出所有可能的取值, 被说明为该“枚举”类型的变量取值不能超过定义的范围。应该说明的是, 枚举类型是一种基本数据类型,而不是一种构造类型, 因为它不能再分解为任何基本类型。 枚举类型的定义和枚举变量的说明 一、枚举的定义枚举类型定义的一般形式为: enum 枚举名 { 枚举值表 }; 在枚举值表中应罗列出所有可用值。这些值也称为枚举元素。 例如: enum weekday { sun,mou,tue,wed,thu,fri,sat }; 该枚举名为weekday,枚举值共有7个,即一周中的七天。 凡被说明为weekday类型变量的取值只能是七天中的某一天。 二、枚举变量的说明 如同结构和联合一样,枚举变量也可用不同的方式说明, 即先定义后说明,同时定义说明或直接说明。设有变量a,b,c被说明为上述的weekday,可采用下述任一种方式: enum weekday { ...... }; enum weekday a,b,c;或者为: enum weekday { ...... }a,b,c;或者为: enum { ...... }a,b,c; 枚举类型变量的赋值和使用 枚举类型在使用中有以下规定: 1. 枚举值是常量,不是变量。不能在程序中用赋值语句再对它赋值。例如对枚举weekday的元素再作以下赋值: sun=5;mon=2;sun=mon; 都是错误的。 2. 枚举元素本身由系统定义了一个表示序号的数值,从0 开始顺序定义为0,1,2…。如在weekday中,sun值为0,mon值为1, …,sat值为6。 main(){ enum weekday { sun,mon,tue,wed,thu,fri,sat } a,b,c; a=sun; b=mon; c=tue; printf("%d,%d,%d",a,b,c); } 3. 只能把枚举值赋予枚举变量,不能把元素的数值直接赋予枚举变量。如: a=sum;b=mon; 是正确的。而: a=0;b=1; 是错误的。如一定要把数值赋予枚举变量,则必须用强制类型转换,如: a=(enum weekday)2;其意义是将顺序号为2的枚举元素赋予枚举变量a,相当于: a=tue; 还应该说明的是枚举元素不是字符常量也不是字符串常量, 使用时不要加单、双引号。 main(){ enum body { a,b,c,d } month[31],j; int i; j=a; for(i=1;i<=30;i++){ month[i]=j; j++; if (j>d) j=a; } for(i=1;i<=30;i++){ switch(month[i]) { case a:printf(" %2d %c\t",i,'a'); break; case b:printf(" %2d %c\t",i,'b'); break; case c:printf(" %2d %c\t",i,'c'); break; case d:printf(" %2d %c\t",i,'d'); break; default:break; } } printf("\n"); } 位运算   前面介绍的各种运算都是以字节作为最基本位进行的。 但在很多系统程序中常要求在位(bit)一级进行运算或处理。C语言提供了位运算的功能, 这使得C语言也能像汇编语言一样用来编写系统程序。 一、位运算符C语言提供了六种位运算符: & 按位与 | 按位或 ^ 按位异或 ~ 取反 << 左移 >> 右移 1. 按位与运算 按位与运算符"&"是双目运算符。其功能是参与运算的两数各对应的二进位相与。只有对应的两个二进位均为1时,结果位才为1 ,否则为0。参与运算的数以补码方式出现。 例如:9&5可写算式如下: 00001001 (9的二进制补码)&00000101 (5的二进制补码) 00000001 (1的二进制补码)可见9&5=1。   按位与运算通常用来对某些位清0或保留某些位。例如把a 的高八位清 0 , 保留低八位, 可作 a&255 运算 ( 255 的二进制数为0000000011111111)。 main(){ int a=9,b=5,c; c=a&b; printf("a=%d\nb=%d\nc=%d\n",a,b,c); } 2. 按位或运算 按位或运算符“|”是双目运算符。其功能是参与运算的两数各对应的二进位相或。只要对应的二个二进位有一个为1时,结果位就为1。参与运算的两个数均以补码出现。 例如:9|5可写算式如下: 00001001|00000101 00001101 (十进制为13)可见9|5=13 main(){ int a=9,b=5,c; c=a|b; printf("a=%d\nb=%d\nc=%d\n",a,b,c); } 3. 按位异或运算 按位异或运算符“^”是双目运算符。其功能是参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1。参与运算数仍以补码出现,例如9^5可写成算式如下: 00001001^00000101 00001100 (十进制为12) main(){ int a=9; a=a^15; printf("a=%d\n",a); } 4. 求反运算 求反运算符~为单目运算符,具有右结合性。 其功能是对参与运算的数的各二进位按位求反。例如~9的运算为: ~(0000000000001001)结果为:1111111111110110 5. 左移运算 左移运算符“<<”是双目运算符。其功能把“<< ”左边的运算数的各二进位全部左移若干位,由“<<”右边的数指定移动的位数, 高位丢弃,低位补0。例如: a<<4 指把a的各二进位向左移动4位。如a=00000011(十进制3),左移4位后为00110000(十进制48)。6. 右移运算 右移运算符“>>”是双目运算符。其功能是把“>> ”左边的运算数的各二进位全部右移若干位,“>>”右边的数指定移动的位数。 例如:设 a=15,a>>2 表示把000001111右移为00000011(十进制3)。 应该说明的是,对于有符号数,在右移时,符号位将随同移动。当为正数时, 最高位补0,而为负数时,符号位为1,最高位是补0或是补1 取决于编译系统的规定。Turbo C和很多系统规定为补1。 main(){ unsigned a,b; printf("input a number: "); scanf("%d",&a); b=a>>5; b=b&15; printf("a=%d\tb=%d\n",a,b); } 请再看一例! main(){ char a='a',b='b'; int p,c,d; p=a; p=(p<<8)|b; d=p&0xff; c=(p&0xff00)>>8; printf("a=%d\nb=%d\nc=%d\nd=%d\n",a,b,c,d); } 位域 有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几个不同的区域, 并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。 这样就可以把几个不同的对象用一个字节的二进制位域来表示。一、位域的定义和位域变量的说明位域定义与结构定义相仿,其形式为: struct 位域结构名 { 位域列表 }; 其中位域列表的形式为: 类型说明符 位域名:位域长度 例如: struct bs { int a:8; int b:2; int c:6; }; 位域变量的说明与结构变量说明的方式相同。 可采用先定义后说明,同时定义说明或者直接说明这三种方式。例如: struct bs { int a:8; int b:2; int c:6; }data; 说明data为bs变量,共占两个字节。其中位域a占8位,位域b占2位,位域c占6位。对于位域的定义尚有以下几点说明: 1. 一个位域必须存储在同一个字节中,不能跨两个字节。如一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域。也可以有意使某位域从下一单元开始。例如: struct bs { unsigned a:4 unsigned :0 /*空域*/ unsigned b:4 /*从下一单元开始存放*/ unsigned c:4 } 在这个位域定义中,a占第一字节的4位,后4位填0表示不使用,b从第二字节开始,占用4位,c占用4位。 2. 由于位域不允许跨两个字节,因此位域的长度不能大于一个字节的长度,也就是说不能超过8位二进位。 3. 位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。例如: struct k { int a:1 int :2 /*该2位不能使用*/ int b:3 int c:2 }; 从以上分析可以看出,位域在本质上就是一种结构类型, 不过其成员是按二进位分配的。 二、位域的使用位域的使用和结构成员的使用相同,其一般形式为: 位域变量名?位域位域允许用各种格式输出。 main(){ struct bs { unsigned a:1; unsigned b:3; unsigned c:4; } bit,*pbit; bit.a=1; bit.b=7; bit.c=15; printf("%d,%d,%d\n",bit.a,bit.b,bit.c); pbit=&bit; pbit->a=0; pbit->b&=3; pbit->c|=1; printf("%d,%d,%d\n",pbit->a,pbit->b,pbit->c); } 上例程序中定义了位域结构bs,三个位域为a,b,c。说明了bs类型的变量bit和指向bs类型的指针变量pbit。这表示位域也是可以使用指针的。 程序的9、10、11三行分别给三个位域赋值。( 应注意赋值不能超过该位域的允许范围)程序第12行以整型量格式输出三个域的内容。第13行把位域变量bit的地址送给指针变量pbit。第14行用指针方式给位域a重新赋值,赋为0。第15行使用了复合的位运算符"&=", 该行相当于: pbit->b=pbit->b&3位域b中原有值为7,与3作按位与运算的结果为3(111&011=011,十进制值为3)。同样,程序第16行中使用了复合位运算"|=", 相当于: pbit->c=pbit->c|1其结果为15。程序第17行用指针方式输出了这三个域的值。 类型定义符typedef C语言不仅提供了丰富的数据类型,而且还允许由用户自己定义类型说明符,也就是说允许由用户为数据类型取“别名”。 类型定义符typedef即可用来完成此功能。例如,有整型量a,b,其说明如下: int aa,b; 其中int是整型变量的类型说明符。int的完整写法为integer, 为了增加程序的可读性,可把整型说明符用typedef定义为: typedef int INTEGER 这以后就可用INTEGER来代替int作整型变量的类型说明了。 例如: INTEGER a,b;它等效于: int a,b; 用typedef定义数组、指针、结构等类型将带来很大的方便,不仅使程序书写简单而且使意义更为明确,因而增强了可读性。例如: typedef char NAME[20]; 表示NAME是字符数组类型,数组长度为20。 然后可用NAME 说明变量,如: NAME a1,a2,s1,s2;完全等效于: char a1[20],a2[20],s1[20],s2[20] 又如: typedef struct stu{ char name[20]; int age; char sex; } STU; 定义STU表示stu的结构类型,然后可用STU来说明结构变量: STU body1,body2; typedef定义的一般形式为: typedef 原类型名 新类型名 其中原类型名中含有定义部分,新类型名一般用大写表示, 以 便于区别。在有时也可用宏定义来代替typedef的功能,但是宏定义是由预处理完成的,而typedef则是在编译时完成的,后者更为灵活方便。 本章小结 1. 枚举是一种基本数据类型。枚举变量的取值是有限的,枚举元素是常量,不是变量。 2. 枚举变量通常由赋值语句赋值,而不由动态输入赋值。枚举元素虽可由系统或用户定义一个顺序值,但枚举元素和整数并不相同,它们属于不同的类型。因此,也不能用printf语句来输出元素值(可输出顺序值)。 3. 位运算是C语言的一种特殊运算功能, 它是以二进制位为单位进行运算的。位运算符只有逻辑运算和移位运算两类。位运算符可以与赋值符一起组成复合赋值符。如&=,|=,^=,>>=,<<=等。 4. 利用位运算可以完成汇编语言的某些功能,如置位,位清零,移位等。还可进行数据的压缩存储和并行运算。 5. 位域在本质上也是结构类型,不过它的成员按二进制位分配内存。其定义、说明及使用的方式都与结构相同。 6. 位域提供了一种手段,使得可在高级语言中实现数据的压缩,节省了存储空间,同时也提高了程序的效率。 7. 类型定义typedef 向用户提供了一种自定义类型说明符的手段,照顾了用户编程使用词汇的习惯,又增加了程序的可读性。 资料收集:beck Copyright 2002 www.vcok.com, All Rights Reserved

69,373

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧