C语言学习(十一)位操作

参考书:《C Primer Plus》第六版

1. 二进制数、位和字节,按位运算符

按位运算符

二进制反码或按位取反:~
按位与:&
按位或:|
按位异或:^
掩码
按位与运算通常用于掩码。
用掩码如:

flags = flags & mask;

常见用法是

ch &=0xff;

0xff的二进制形式为11111111,八进制形式为0377。这个掩码保持ch中的后8为不变,其他位设为0。
按位或运算用于打开位。

flags|=MASK;

关闭位如:

flags&=~MASK;

切换位用按位异或操作:

flags^=MASK;

检查某个位的值:

if((flags&MASK)==MASK){
	..;
}

移位运算符

左移:<<number << n:number乘以2的n次幂
右移:>>number >> n:number除以2的n次幂
移位运算符对于2的幂提供了快速有效的乘除法。

程序清单1:

#include"stdio.h"
#include"limits.h"
char * itobs(int ,char *);
void show_bstr(const char *);
int main(void){
    char bit_str[CHAR_BIT*sizeof(int)+1];
    int number;

    puts("Enter integers and see them in binary.");
    puts("Non-numeric input terminates program.");
    while(scanf("%d",&number)==1){
        itobs(number,bit_str);//将一个整数转换位一个二进制字符串
        printf("%d is ",number);
        show_bstr(bit_str);
        putchar('\n');
    }
    puts("Bye!");
    return 0;
}
char *itobs(int n,char *ps){
    int i;
    const static int size =CHAR_BIT*sizeof(int);
    for(i=size-1;i>=0;i--,n>>=1)
        ps[i]=(01 & n)+'0';
    ps[size]='\0';
    return ps;
}
void show_bstr(const char *str){
    int i=0;
    while(str[i]){
        putchar(str[i]);
        if(++i%4==0 &&str[i])
            putchar(' ');
    }
}
root@DESKTOP-624LRQ5:/mnt/d/Program Files/code/c15# ./list1
Enter integers and see them in binary.
Non-numeric input terminates program. 
123
123 is 0000 0000 0000 0000 0000 0000 0111 1011
231
231 is 0000 0000 0000 0000 0000 0000 1110 0111
221
221 is 0000 0000 0000 0000 0000 0000 1101 1101
321331
321331 is 0000 0000 0000 0100 1110 0111 0011 0011
123321
123321 is 0000 0000 0000 0001 1110 0001 1011 1001
12312
12312 is 0000 0000 0000 0000 0011 0000 0001 1000
q
Bye!
root@DESKTOP-624LRQ5:/mnt/d/Program Files/code/c15# 

程序清单2

#include"stdio.h"
#include"limits.h"
char * itobs(int ,char *);
void show_bstr(const char *);
int invert_end(int num,int bits);
int main(void){
    char bit_str[CHAR_BIT*sizeof(int)+1];
    int number;

    puts("Enter integers and see them in binary.");
    puts("Non-numeric input terminates program.");
    while(scanf("%d",&number)==1){
        itobs(number,bit_str);//将一个整数转换位一个二进制字符串
        printf("%d is ",number);
        show_bstr(bit_str);
        putchar('\n');
        number=invert_end(number,4);
        printf("Iverting the last 4 bits gives\n");
        show_bstr(itobs(number,bit_str));
        putchar('\n');
    }
    puts("Bye!");
    return 0;
}
char *itobs(int n,char *ps){
    int i;
    const static int size =CHAR_BIT*sizeof(int);
    for(i=size-1;i>=0;i--,n>>=1)
        ps[i]=(01 & n)+'0';
    ps[size]='\0';
    return ps;
}
void show_bstr(const char *str){
    int i=0;
    while(str[i]){
        putchar(str[i]);
        if(++i%4==0 &&str[i])
            putchar(' ');
    }
}
int invert_end(int number,int bits){
    int mask=0;
    int bitval=1;
    while(bits-- >0){
        mask |=bitval;
        bitval <<= 1;
    }
    return number^mask;
}
Enter integers and see them in binary.
Non-numeric input terminates program.
7
7 is 0000 0000 0000 0000 0000 0000 0000 0111
Iverting the last 4 bits gives
0000 0000 0000 0000 0000 0000 0000 1000
23
23 is 0000 0000 0000 0000 0000 0000 0001 0111
Iverting the last 4 bits gives
0000 0000 0000 0000 0000 0000 0001 1000
123
123 is 0000 0000 0000 0000 0000 0000 0111 1011
Iverting the last 4 bits gives
0000 0000 0000 0000 0000 0000 0111 0100
Bye!

2. 位字段

位字段是一个signed int或unsigned int 类型的变量中的一组相邻的位。为字段通过一个结构声明来建立,声明时为每个字段提供标签,并确定该字段的宽度。如下:

struct
{
    unsigned int a:1;
    unsigned int b:2;
    unsigned int c:1;
    unsigned int d:3;
} s;

3. 编程练习

  1. 编写一个函数把二进制字符转换为一个数字
#include<stdio.h>
#include<stdlib.h>

int toDigit(char *ch);
int main(void){
    char ch;
    char str[20];
    puts("Enter a binary number:");
    while(scanf("%s",str)==1){
        printf("-->%d\n",toDigit(str));
        puts("Next:");
    }
    puts("Bye.");
    return 0;
}
int toDigit(char *ch){
    int i=0,value=0;
    while(ch[i]!='\0'){
        if(ch[i]=='1'){
            value<<=1;
            value++;
        }else if(ch[i]=='0')
            value<<=1;
        else
            return 0;
        i++;
    }
    return value;
}
Enter a binary number:
000111
-->7 
Next:
11001
-->25
Next:
111111
-->63
Next:
1111111
-->127
Next: 
1000000
-->64
Next:
s
-->0 
Next:
Bye.
  1. 编写一个程序,通过命令行参数读取两个二进制字符串,然后对这两个二进制字符串做一些位操作并输出。
#include"stdio.h"
#include"stdlib.h"
#include"limits.h"
char* toString(int i);
int todigit(char*);
int main(int argc,char **argv){
    if(argc<3){
        puts("arguments not enough");
        exit(EXIT_FAILURE);
    }
    int v1=todigit(argv[1]);
    int v2=todigit(argv[2]);
    printf("v1=%d ,v2=%d, ~v1=%d,~v2=%d\n",v1,v2,~v1,~v2);
    printf("~%s-->%s,~%s-->%s\n",argv[1],toString(~v1),argv[2],toString(~v2));
    printf("%s & %s = %s\n",argv[1],argv[2],toString(v1&v2));
    printf("%s | %s = %s\n",argv[1],argv[2],toString(v1|v2));
    printf("%s ^ %s = %s\n",argv[1],argv[2],toString(v1^v2));
    return 0;
}
int todigit(char *ch){
    int i=0,sum=0;
    while(ch[i]!='\0'){
        if(ch[i]=='1'){
            sum<<=1;
            sum++;
        }else if(ch[i]=='0')
            sum<<=1;
        else
            return 0;
        i++;
    }
    return sum;
}
char * toString(int val){
    int i;
    const static int size=CHAR_BIT*sizeof(int);
    char static str[CHAR_BIT*sizeof(int)+1];
    for(i=size-1;i>=0;i--,val>>=1)
        str[i]=(01&val)+'0';
    str[size]='\0';
    return str;
}
```bash
root@DESKTOP-624LRQ5:/mnt/d/Program Files/code/c15# ./prac2 11001 100001111
v1=25 ,v2=271, ~v1=-26,~v2=-272
~11001-->11111111111111111111111111100110,~100001111-->11111111111111111111111111100110
11001 & 100001111 = 00000000000000000000000000001001
11001 | 100001111 = 00000000000000000000000100011111
11001 ^ 100001111 = 00000000000000000000000100010110
root@DESKTOP-624LRQ5:/mnt/d/Program Files/code/c15#
  1. 编写一个函数,接受一个int,返回参数中打开位的数量。
#include<stdio.h>

int num(int val);
int main(void){
    int v;
    puts("Enter an integer:");
    while(scanf("%d",&v)==1){
        printf("number:%d\n",num(v));
        printf("Next:\n");
    }
    puts("Bye.");
    return 0;
}
int num(int val){
    int i,sum=0;
    while(val!=0){
        sum+=(val%2?1:0);
        val>>=1;
    }
    return sum;
}
Enter an integer:
7
number:3
Next:
5
number:2
Next:
15
number:4
Next:
99
number:4
Next:
6
number:2
Next:
  1. 编写一个函数接受两个int参数,一个为值,一个为位的位置,返回0或1
#include"stdio.h"
#include"stdlib.h"
int bit(int val,int ind);
int main(void){
    int val,ind;
    puts("Enter two integer:");
    while(scanf("%d %d",&val,&ind)==2){
        printf("The value is :%d\n",bit(val,ind));
        puts("Next");
    }
    puts("Bye.");
    return 0;
}
int bit(int val,int ind){
    return (val>>ind)%2;
}
root@DESKTOP-624LRQ5:/mnt/d/Program Files/code/c15# ./prac4
Enter two integer:
8 2
The value is :0
Next
127 4
The value is :1
Next
44 3
The value is :1
Next
55 4
The value is :1
Next
Bye.
  1. 编写一个函数把一个unsigned int中的位向左旋转指定数量的位。
#include"stdio.h"
#include"stdlib.h"
#include"limits.h"
int rotate(int x,int ind);
int main(void){
    puts("Enter two integer:");
    int x,i;
    while(scanf("%d %d",&x,&i)==2){
        printf("%d rotate -- %d -->%d \n",x,i,rotate(x,i));
        puts("Next:");
    }
    puts("Bye.");
    return 0;
}
int rotate(int x,int ind){
    int m=0;
    int i,xc=x,bits=0;;
    while(xc!=0){
        xc>>=1;
        bits++;
    }
    for(i=0;i<ind;i++){
        m=(x>>(bits-1))%2;
        x<<=1;
        x=x-(m<<bits)+m;
    }
    return x;
}
Enter two integer:
7
2
7 rotate -- 2 -->7 
Next:
8 2
8 rotate -- 2 -->2 
Next:
255 4
255 rotate -- 4 -->255 
Next:
256 4
256 rotate -- 4 -->8 
Next:
Bye.
  1. 设计一个字段程序存储文本一些属性信息。
#include"stdio.h"
#include"stdlib.h"
struct textStyle{
    unsigned int fontId:8;
    unsigned int fontSize:7;
    unsigned int align:2;
    unsigned int bold:1;
    unsigned int italic:1;
    unsigned int underline:1;
};
void show(struct textStyle);
int main(void){
    struct textStyle ts={1,12,0,0,0,0};
    show(ts);
    char ch='f';
    int val;
    while((ch=getchar())!='q'){
        switch (ch)
        {
        case 'f':
            printf("Enter font id (0-255): ");
            scanf("%d",&val);
            ts.fontId=val;
            show(ts);
            break;
        case 's':
            printf("Enter font size (0-127): ");
            scanf("%d",&val);
            ts.fontSize=val;
            show(ts);
            break;
        case 'a':
            printf("Select alignment:\n");
            printf("l)left      c)center    r)right\n");
            char chh='l';
            getchar();
            if((chh=getchar())=='l')
                ts.align=0;
            else if(chh=='c')
                ts.align=1;
            else if(chh=='r')
                ts.align=2;
            show(ts);
            break;
        case 'b':
            ts.bold=ts.bold==0?1:0;
            show(ts);
            break;
        case 'i':
            ts.italic=ts.italic==0?1:0;
            show(ts);
            break;
        case 'u':
            ts.underline=ts.underline==0?1:0;
            show(ts);
            break;
        default:
            break;
        }
    }
    puts("Bye.");
    return 0;

}
void show(struct textStyle ts){
    printf("ID  SIZE  ALIGNMENT   B   I   U\n");
    printf(" %d   %d    %s    %s  %s  %s\n",ts.fontId,ts.fontSize,ts.align==0?"left":ts.align==1?"center":"right",
    ts.bold==0?"off":"on",ts.italic==0?"off":"on",ts.underline==0?"off":"on");
    puts("f)change font     s)change size       a)change alignment");
    puts("b)toggle bold     i)touggle italic    u)toggle underline");
    puts("q)quit");
}
root@DESKTOP-624LRQ5:/mnt/d/Program Files/code/c15# ./prac6
ID  SIZE  ALIGNMENT   B   I   U
 1   12    left    off  off  off
f)change font     s)change size       a)change alignment
b)toggle bold     i)touggle italic    u)toggle underline
q)quit
a
Select alignment:
l)left      c)center    r)right
l
ID  SIZE  ALIGNMENT   B   I   U
 1   12    left    off  off  off
f)change font     s)change size       a)change alignment
b)toggle bold     i)touggle italic    u)toggle underline
q)quit
a
Select alignment:
l)left      c)center    r)right
c
ID  SIZE  ALIGNMENT   B   I   U
 1   12    center    off  off  off
f)change font     s)change size       a)change alignment
b)toggle bold     i)touggle italic    u)toggle underline
q)quit
b
ID  SIZE  ALIGNMENT   B   I   U
 1   12    center    on  off  off
f)change font     s)change size       a)change alignment
b)toggle bold     i)touggle italic    u)toggle underline
q)quit
i
ID  SIZE  ALIGNMENT   B   I   U
 1   12    center    on  on  off
f)change font     s)change size       a)change alignment
b)toggle bold     i)touggle italic    u)toggle underline
q)quit
u
ID  SIZE  ALIGNMENT   B   I   U
 1   12    center    on  on  on
f)change font     s)change size       a)change alignment
b)toggle bold     i)touggle italic    u)toggle underline
q)quit
q
Bye.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值