按位取反运算符:~,作用:将对应二进制码取反。代码示例example.c:
#include <stdio.h>
int main(void)
{
unsigned char val = 2; // 00000010
unsigned char new_val = ~val; // 11111101
printf("Now val is %d\n", val);
printf("Now new_val is %d\n", new_val);
return 0;
}
输出结果:
![](https://img-blog.csdnimg.cn/img_convert/6a5be4c891f84933b96e92e5ccede6b4.png)
按位与运算符:&,作用:两个二进制位都为真时取真。代码示例example.c :
#include <stdio.h>
int main(void)
{
unsigned char var1 = 0x93; // 147 10010011
unsigned char var2 = 0x3d; // 61 00111101
unsigned char var3 = var1 & var2; //0x11 17 00010001
printf("var1 is %d\n", var1);
printf("var2 is %d\n", var2);
printf("var3 is %d\n", var3);
var1 &= var2; //Equal to var1 = var1 & var2;
printf("Now var1 is %d\n", var1);
return 0;
}
输出结果:
![](https://img-blog.csdnimg.cn/img_convert/dc34cf5faf998f59e6fb6bab689eaa8a.png)
按位或运算符:|,作用:当两个二进制位有一个为真时取真。代码示例example.c:
#include <stdio.h>
int main(void)
{
unsigned char var1 = 0x93; // 10010011 147
unsigned char var2 = 0x3d; // 00111101 61
unsigned char var3 = var1 | var2; // 10111111 0xbf 191
printf("var1 = %d\n", var1);
printf("var2 = %d\n", var2);
printf("var3 = %d\n", var3);
var1 |= var2; // Equal to var1 = var1 | var2
printf("Now var1 = %d\n", var1);
return 0;
}
输出结果:
![](https://img-blog.csdnimg.cn/img_convert/e5d87ab3a1c5e8dd6d267f52378583ec.png)
按位异或运算符:^,作用:当且仅当两个二进制位中仅有一个为真时取真。代码示例example.c:
#include <stdio.h>
int main(void)
{
unsigned char var1 = 0x93; // 10010011 147
unsigned char var2 = 0x3d; // 00111101 61
unsigned char var3 = var1 ^ var2; // 10101110 0xae 174
printf("var1 = %d\n", var1);
printf("var2 = %d\n", var2);
printf("var3 = %d\n", var3);
var1 ^= var2; // Equal to var1 = var1 ^ var2;
printf("Now var1 = %d\n", var1);
return 0;
}
输出结果:
![](https://img-blog.csdnimg.cn/img_convert/d7c07a0c6afd4f67beb061d7271b4e4b.png)
左移运算符:<<,作用:将其左侧运算对象每一位的值向左移动其右侧运算对象指定的位数,左侧运算对象移除左末端位的值丢失,用0填充空出的位置。示例代码:example.c
#include <stdio.h>
int main(void)
{
int stonk = 1; // 00000001
int onkoo;
onkoo = stonk << 2; // 00000100
stonk <<= 2;
printf("onkoo = %d\n", onkoo);
printf("stonk = %d\n", stonk);
return 0;
}
输出结果:
![](https://img-blog.csdnimg.cn/img_convert/34448ca20475cd457a08e80dc6348e2f.png)
右移运算符:>>,作用:将其左侧运算对象每一位的值向右移动其右侧运算对象指定的位数,左侧运算对象移除右末端位的值丢失,对于有符号类型,取决于机器用0或者1填充空出的位置,对于无符号类型,都用0填充空出的位置。示例代码example.c:
#include <stdio.h>
int main(void)
{
signed char var1 = 0x8a; // 10001010 -(256-138) = -118
signed char var2 = var1 >> 2; // 11100010 -(256 - 0xe2) = -(256-226) = -30
unsigned char var3 = 0x8a >> 2; // 00100010 0x22 34
printf("var1 = %d\n", var1);
printf("var2 = %d\n", var2);
printf("var3 = %d\n", var3);
return 0;
}
输出结果:
![](https://img-blog.csdnimg.cn/img_convert/3937fcae27f9ba0e26210b4b8e1b33ec.png)
程序清单15.1,binbit.c:
/*binbit.c -- 使用位操作显示二进制 */
#include <stdio.h>
#include <limits.h> //提供 CHAR_BIT 的定义,CHAR_BIT 表示每字节的位数
char * itobs(int, char *);
void show_bstr(const char *);
int main(void)
{
char bin_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, bin_str);
printf("%d is ", number);
show_bstr(bin_str);
putchar('\n');
}
puts("Bye!");
return 0;
}
char * itobs(int n, char * ps)
{
int i;
static const int size = CHAR_BIT * sizeof(int);
for (i = size - 1; i >= 0; i--, n >>=1) // 7 -> 0000 0111
ps[i] = (01 & n) + '0'; // 0000 0001
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(' ');
}
}
输出结果:
![](https://img-blog.csdnimg.cn/img_convert/3f97df3e17a82fc1864d3fb88b0e2fc0.png)
程序清单15.2, invert4.c:
/*invert4.c -- 使用位操作显示二进制 */
#include <stdio.h>
#include <limits.h> //提供 CHAR_BIT 的定义,CHAR_BIT 表示每字节的位数
char * itobs(int, char *);
void show_bstr(const char *);
int invert_end(int num, int bits);
int main(void)
{
char bin_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, bin_str);
printf("%d is ", number);
show_bstr(bin_str);
putchar('\n');
number = invert_end(number, 4);
printf("Inverting the last 4 bits gives\n");
show_bstr(itobs(number, bin_str));
putchar('\n');
}
puts("Bye!");
return 0;
}
char * itobs(int n, char * ps)
{
int i;
static const int size = CHAR_BIT * sizeof(int);
for (i = size - 1; i >= 0; i--, n >>= 1) // 7 -> 0000 0111
ps[i] = (01 & n) + '0'; // 0000 0001
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 num, int bits)
{
int mask = 0;
int bitval = 1;
while (bits-- > 0)
{
mask |= bitval;
bitval <<= 1;
}
return num ^ mask;
}
输出结果:
![](https://img-blog.csdnimg.cn/img_convert/d153f07f0ebee92167842b7f8e5935d7.png)
程序清单15.3,fields.c:
/* fields.c -- 定义并使用字段 */
#include <stdio.h>
#include <stdbool.h>
/* 线的样式 */
#define SOLID 0
#define DOTTED 1
#define DASHED 2
/* 三原色 */
#define BLUE 4
#define GREEN 2
#define RED 1
/* 混合色 */
#define BLACK 0
#define YELLOW (RED | GREEN)
#define MAGENTA (RED | BLUE)
#define CYAN (GREEN | BLUE)
#define WHITE (RED | GREEN | BLUE)
const char * colors[8] = { "black", "red", "green", "yellow",
"blue", "magenta", "cyan", "white" };
struct box_props {
bool opaque : 1;
unsigned int fill_color : 3;
unsigned int : 4;
bool show_border : 1;
unsigned int border_color : 3;
unsigned int border_style : 2;
unsigned int : 2;
};
void show_settings(const struct box_props * pb);
int main(void)
{
/* 创建并使用 box_props 结构 */
struct box_props box = { true, YELLOW, true, GREEN, DASHED };
printf("Original box settings:\n");
show_settings(&box);
box.opaque = false;
box.fill_color = WHITE;
box.border_color = MAGENTA;
box.border_style = SOLID;
printf("\nModified box settings:\n");
show_settings(&box);
return 0;
}
void show_settings(const struct box_props * pb)
{
printf("Box is %s.\n", pb->opaque == true ? "opaque" : "transparent");
printf("The fill color is %s.\n", colors[pb->fill_color]);
printf("Border %s.\n", pb->show_border == true ? "shown" : " not shown");
printf("The border color is %s.\n", colors[pb->border_color]);
printf("The border style is ");
switch (pb->border_style)
{
case SOLID: printf("solid.\n"); break;
case DOTTED: printf("dotted.\n"); break;
case DASHED: printf("dashed.\n"); break;
default: printf("unknown type.\n");
}
}
输出结果:
![](https://img-blog.csdnimg.cn/img_convert/4131089b5326874efd69f7895597d87d.png)
程序清单15.4, dualview.c:
/* dualview.c -- 位字段和按位运算符 */
#include <stdio.h>
#include <stdbool.h>
#include <limits.h>
/* 位字段符号常量 */
/* 边框线样式 */
#define SOLID 0
#define DOTTED 1
#define DASHED 2
/* 三原色 */
#define BLUE 4
#define GREEN 2
#define RED 1
/* 混合色 */
#define BLACK 0
#define YELLOW (RED | GREEN)
#define MAGENTA (RED | BLUE)
#define CYAN (GREEN | BLUE)
#define WHITE (RED | GREEN | BLUE)
/* 按位方法用到的符号常量 */
#define OPAQUE 0x1
#define FILL_BLUE 0x8
#define FILL_GREEN 0x4
#define FILL_RED 0x2
#define FILL_MASK 0xE
#define BORDER 0x100
#define BORDER_BLUE 0x800
#define BORDER_GREEN 0x400
#define BORDER_RED 0x200
#define BORDER_MASK 0xE00
#define B_SOLID 0
#define B_DOTTED 0x1000
#define B_DASHED 0x2000
#define STYLE_MASK 0x3000
const char * colors[8] = { "black", "red", "green", "yellow", "blue", "magenta",
"cyan", "white" };
struct box_props {
bool opaque : 1;
unsigned int fill_color : 3;
unsigned int : 4;
bool show_border : 1;
unsigned int border_color : 3;
unsigned int border_style : 2;
unsigned int : 2;
};
union Views /* 把数据看作结构或 unsigned short 类型的变量 */
{
struct box_props st_view;
unsigned short us_view;
};
void show_settings(const struct box_props * pb);
void show_settings1(unsigned short);
char * itobs(int n, char * ps);
int main(void)
{
/* 创建 Views 联合,并初始化initialize struct box view */
union Views box = { { true, YELLOW, true, GREEN, DASHED } };
char bin_str[8 * sizeof(unsigned int) + 1];
printf("Original box settings:\n");
show_settings(&box.st_view);
printf("\nBox settings using unsigned int view:\n");
show_settings1(box.us_view);
printf("bits are %s\n", itobs(box.us_view, bin_str));
box.us_view &= ~FILL_MASK; /* 把表示填充色的位清0 */
box.us_view |= (FILL_BLUE | FILL_GREEN); /* 重置填充色 */
box.us_view ^= OPAQUE; /* 切换是否透明的位 */
box.us_view |= BORDER_RED; /* 错误的方法 */
box.us_view &= ~STYLE_MASK;/* 把样式的位清0 */
box.us_view |= B_DOTTED; /* 把样式设置为点 */
printf("\nModified box settings:\n");
show_settings(&box.st_view);
printf("\nBox settings using unsigned int view:\n");
show_settings1(box.us_view);
printf("bits are %s\n", itobs(box.us_view, bin_str));
return 0;
}
void show_settings(const struct box_props * pb)
{
printf("Box is %s.\n", pb->opaque == true ? "opaque" : "transparent");
printf("The fill color is %s.\n", colors[pb->fill_color]);
printf("Border %s.\n", pb->show_border == true ? "shown" : " not shown");
printf("The border color is %s.\n", colors[pb->border_color]);
printf("The border style is ");
switch (pb->border_style)
{
case SOLID : printf("solid.\n"); break;
case DOTTED: printf("dotted.\n"); break;
case DASHED: printf("dashed.\n"); break;
default : printf("unknown type.\n");
}
}
void show_settings1(unsigned short us)
{
printf("box is %s.\n", (us & OPAQUE) == OPAQUE ? "opaque" : "transparent");
printf("The fill color is %s.\n", colors[(us >> 1) & 07]);
printf("Border %s.\n", (us & BORDER) == BORDER ? "shown" : "not shown");
printf("The border style is ");
switch (us & STYLE_MASK)
{
case B_SOLID : printf("solid.\n"); break;
case B_DOTTED : printf("dotted.\n"); break;
case B_DASHED : printf("dashed.\n"); break;
default : printf("unknow type.\n");
}
printf("The border color is %s.\n", colors[(us >> 9) & 07]);
}
char * itobs(int n, char * ps)
{
int i;
static const int size = CHAR_BIT * sizeof(int);
for (i = size - 1; i >= 0; i--, n >>=1) // 7 -> 0000 0111
ps[i] = (01 & n) + '0'; // 0000 0001
ps[size] = '\0';
return ps;
}
输出结果:
![](https://img-blog.csdnimg.cn/img_convert/a043a84aaf610abcc322ee08db4dd5b0.png)
程序清单15.5,align.c:
/* align.c -- 使用 _Alignof 和 _Alignas (C!!) */
#include <stdio.h>
int main(void)
{
double dx;
char ca;
char cx;
double dz;
char cb;
char _Alignas(double) cz;
printf("char alignment: %zd\n", _Alignof(char));
printf("double alignment: %zd\n", _Alignof(double));
printf("&dx: %p\n", &dx);
printf("&ca: %p\n", &ca);
printf("&cx: %p\n", &cx);
printf("&dz: %p\n", &dz);
printf("&cb: %p\n", &cb);
printf("&cz: %p\n", &cz);
return 0;
}
输出结果:
![](https://img-blog.csdnimg.cn/img_convert/1a62e895e5e5bf99c460d3043b27302d.png)
编程练习:
![](https://img-blog.csdnimg.cn/img_convert/f52c8ebeac9edf81abb349ac86d44d62.png)
![](https://img-blog.csdnimg.cn/img_convert/aacaccf925e9d628480715ebddf2509a.png)
![](https://img-blog.csdnimg.cn/img_convert/a2b06ab0c80f1e17b551d8fb67bd2c7e.png)
题目1
方法一:使用位操作。代码示例15_1_1.c:
#include <stdio.h>
#include <ctype.h> // 提供 isspace() 函数
#include <string.h> // 提供 strchr() 函数
#define SIZE 50
int get_bstr(char * st, int n);
char * del_space(char * st);
int btoi(char * st);
int main(void)
{
char binstr[SIZE];
int number;
printf("Please input a binary string, [Enter] to quit: ");
while(get_bstr(binstr, SIZE))
{
number = btoi(del_space(binstr));
printf("Binary string %s is %d in decimal.\n", binstr, number);
printf("Please input another binary string, [Enter] to quit: ");
}
return 0;
}
int get_bstr(char * st, int n) //通过指针获取字符串并返回字符串的长度
{
char ch;
int i;
//获取仅含 0或1 的字符串 ,注意通过 getchar() 获取的是字符而不是数字,加单引号
for (i = 0; i < n - 1 && (ch = getchar()) != '\n' && (ch == '1' || ch == '0'
|| isspace(ch)); i++)
st[i] = ch;
st[i] = '\0'; //最后一个字符设为空字符
//处理超出 n的大小的字符
if (ch != '\n')
while (getchar() != '\n')
continue;
return i;
}
char * del_space(char * st) // 删去字符中的空格(指针改变了字符串 st)
{
int i;
char * find = NULL;
while ((find = strchr(st, ' ')))
{
for (i = 0; find[i]; i++) // find[i] Equal to *(find + i)
find[i] = find[i + 1];
}
return st;
}
int btoi(char * st) // 通过按位或运算符生成一个目标数
{
int num = 0;
int i;
for (i = 0; st[i]; i++)
{
num <<= 1; // Equal to num = num << 1
num |= (st[i] - '0'); // Equal to num = num | (st[i] - '0')
}
return num;
}
输出结果:
![](https://img-blog.csdnimg.cn/img_convert/74b5f033d719d52f656266fe12049c1f.png)
方法二:直接计算,两种方法。代码示例15_1_2.c:
#include <stdio.h>
#include <string.h> // 提供 strlen() 函数
#define SIZE 50
int btoi(char * st);
int btoi1(char * st);
int main(void)
{
char str[SIZE];
printf("Please input a binary string: ");
gets(str);
printf("Binary string %s is %d in decimal.\n", str, btoi(str));
printf("Binary string %s is %d in deciaml.\n", str, btoi1(str));
return 0;
}
int btoi(char * st)
{
int sum = 0;
while (*st) // 读取字符时从左往右读取,每多读取一个数就增大两倍
{
sum *= 2;
sum += *st - '0';
st++;
}
return sum;
}
int btoi1(char * st) // 从左往右理解二进制字符串,直观理解
{
int sum = 0;
int len = strlen(st);
int i, exp;
for (i = len - 1, exp = 1; i >= 0; i--, exp *= 2)
sum += exp * (st[i] - '0');
return sum;
}
输出结果:
![](https://img-blog.csdnimg.cn/img_convert/8a2baeec74dd2a8f9c915d064d5b70a2.png)
题目2
方法一:先转换为数字,运算完成后再转换为字符,递归实现。代码示例15_2_1.c:
#include <stdio.h>
#include <ctype.h> // 提供 isspace() 函数
#include <string.h> // 提供 strchr() 函数
#include <stdlib.h> // 提供 EXIT_FAILURE
#define SIZE 50
int btoi(char * st);
void print_bstr(unsigned int n);
int main(int argc, char * argv[])
{
int num1, num2;
if (argc != 3)
{
fprintf(stderr, "Usage: %s, binary_str1, binary_str2\n", *argv);
exit(EXIT_FAILURE);
}
num1 = btoi(argv[1]);
num2 = btoi(argv[2]);
printf("num1 = %d\n", num1);
printf("~num1 = %d\n", ~num1);
printf("~%s is ", argv[1]);
print_bstr(~num1);
putchar('\n');
printf("~%s is ", argv[2]);
print_bstr(~num2);
putchar('\n');
printf("%s & %s is ", argv[1], argv[2]);
print_bstr(num1 & num2);
putchar('\n');
printf("%s | %s is ", argv[1], argv[2]);
print_bstr(num1 | num2);
putchar('\n');
printf("%s ^ %s is ", argv[1], argv[2]);
print_bstr(num1 ^ num2);
putchar('\n');
return 0;
}
int btoi(char * st) // 通过按位或运算符生成一个目标数
{
int num = 0;
int i;
for (i = 0; st[i]; i++)
{
num <<= 1; // Equal to num = num << 1
num |= (st[i] - '0'); // Equal to num = num | (st[i] - '0')
}
return num;
}
void print_bstr(unsigned int n) // 以二进制字符格式输出一个数的二进制格式
{
static long loop = 0; // 函数执行期间该值不变
if (!loop && !n)
{
putchar('0');
return;
}
if (n)
{
loop++;
print_bstr(n / 2);
}
else
return;
putchar('0' + (n % 2));
if ((--loop % 4) == 0)
putchar(' ');
}
输出结果:
![](https://img-blog.csdnimg.cn/img_convert/f9f1c49f3369ee9344701933446de685.png)
方法二:先转换为数字,运算完成后再转换为字符,位操作实现。代码示例15_2_1.c:
#include <stdio.h>
#include <stdlib.h> // 提供 EXIT_FAILURE
int bstr_to_dec(const char * str); // 2 进制字符串转换为 10 进制
char *itobs(int n, char *str); // 将一个数转换为 2 进制字符串
int main(int argc, char *argv[])
{
char bstr[8 * sizeof(int) + 1];
if (argc != 3)
{
fprintf(stderr, "Usage: %s binarynum1 binarynum2\n", argv[0]);
exit(EXIT_FAILURE);
}
int v1 = bstr_to_dec(argv[1]);
int v2 = bstr_to_dec(argv[2]);
printf("~%s = %s\n", argv[1], itobs(~v1, bstr));
printf("~%s = %s\n", argv[2], itobs(~v2, bstr));
printf("%s & %s = %s\n", argv[1], argv[2], itobs(v1 & v2, bstr));
printf("%s | %s = %s\n", argv[1], argv[2], itobs(v1 | v2, bstr));
printf("%s ^ %s = %s\n", argv[1], argv[2], itobs(v1 ^ v2, bstr));
return 0;
}
int bstr_to_dec(const char * str)
{
int val = 0;
while (*str)
val = val * 2 + ((*str++) - '0');
return val;
}
char *itobs(int n, char *str)
{
int sz = 8 * sizeof(int);
for (int i = sz - 1; i >= 0; --i, n >>= 1)
str[i] = (n & 1) + '0';
str[sz] = '\0';
return str;
}
输出结果:
![](https://img-blog.csdnimg.cn/img_convert/7381834c699a44194d7bad958351a47e.png)
方法三:按位直接计算,但该方法不适用于计算取反~。示例代码15_2_3.c:
#include <stdio.h>
#include <stdlib.h> //提供 EXIT_FAILURE
void funca(char *a, char *b); // &运算
void funcb(char *a, char *b); // ^运算
void funcc(char *a, char *b); // |运算
int main(int argc, char **argv)
{
char ch;
if(argc != 4)
{
fprintf(stderr, "Usage:%s [string] [string] [char]\n", argv[0]);
exit(EXIT_FAILURE);
}
ch = argv[3][0];
switch(ch)
{
case '1'://不能用位运算符作为识别符号,不符合命令行格式
funca(argv[1], argv[2]);
break;
case '2':
funcb(argv[1], argv[2]);
break;
case '3':
funcc(argv[1], argv[2]);
break;
default: fprintf(stderr, "Wrong!\n");
break;
}
return 0;
}
void funca(char *a, char *b)
{
while(*a && *b)
{
int x = ((*a) - '0') & ((*b) - '0');
putchar(x + '0');
a++;
b++;
}
putchar('\n');
}
void funcb(char *a, char *b)
{
while(*a && *b)
{
int x = ((*a) - '0') ^ ((*b) - '0');
putchar(x + '0');
a++;
b++;
}
putchar('\n');
}
void funcc(char *a, char *b)
{
while(*a && *b)
{
int x = ((*a) - '0') | ((*b) - '0');
putchar(x + '0');
a++;
b++;
}
putchar('\n');
}
输出结果:
![](https://img-blog.csdnimg.cn/img_convert/4651c8d9ca7df6cc7e7b9e8c94772320.png)
题目3
方法一:直接按位&运算。示例代码15_3_1.c:
#include <stdio.h>
int count_openbit(unsigned int n);
int main(void)
{
int num;
printf("Please input an integer(q to quit): ");
while (scanf("%d", &num))
{
while (getchar() != '\n')
continue;
printf("Here are %d bits opend in %d.\n", count_openbit(num), num);
printf("Please input an integer(q to quit): ");
}
return 0;
}
int count_openbit(unsigned int n)
{
int count = 0;
while (n)
{
count += (n & 1);
n >>= 1;
}
return count;
}
输出结果:
![](https://img-blog.csdnimg.cn/img_convert/7c1b6bce89998f3aeafc6af31b80daec.png)
方法二:显示详细信息。示例代码15_3_2.c:
#include <stdio.h>
#define TEST_NUM 9
char * itobs(int n, char *str);
int onbits(int x);
int main(void)
{
int x = TEST_NUM;
char bstr[8 * sizeof(int) + 1];
printf("%d(%s) has %d bit on.\n", x, itobs(x, bstr), onbits(x));
return 0;
}
char *itobs(int n, char *str)
{
int sz = 8 * sizeof(int);
for (int i = sz - 1; i >= 0; --i, n >>= 1)
{
str[i] = (n & 1) + '0';
}
str[sz] = '\0';
return str;
}
int onbits(int x)
{
int sum = 0;
for (int i = 8 * sizeof(int) - 1; i >= 0; --i)
{
sum += (x >> i) & 1;
}
return sum;
}
输出结果:
![](https://img-blog.csdnimg.cn/img_convert/529157b73ec7de511c8f79cbcddc7992.png)
题目4
方法:移动数的位进行按位与运算,两个函数实现相同的功能。示例代码15_4.c:
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#define TEST_VALUE 9 // 1001
bool isbit_open(int num, int pos);
bool isbit_open1(int num, int pos);
int main(void)
{
int size = 8 * sizeof(int);
int i;
for (i = 0; i < size; i++)
printf("The %dth of %d is %s.\n", i + 1,
TEST_VALUE, isbit_open(TEST_VALUE, i + 1) ? "opend" : "closed");
return 0;
}
bool isbit_open(int num, int pos)
{
if (pos <= 0)
{
fputs("The position can't be 0.", stderr);
exit(1);
}
return (num & (1 << (pos - 1)));
}
bool isbit_open1(int num, int pos)
{
if (pos <= 0)
{
fputs("The position can't be 0.", stderr);
exit(1);
}
return (num >> (pos - 1)) & 1;
}
函数1或2输出结果:
![](https://img-blog.csdnimg.cn/img_convert/4bccd52fd79c7547f1f96cc3a9b586c3.png)
题目5
方法:循环移动或者直接移动位,两种函数实现功能相同,示例代码15_5.c:
#include <stdio.h>
#include <limits.h> //Support for CHAR_BIT
#define TEST_VALUE 9
char * itobs(int n, char *str);
unsigned int rotate_l(unsigned int num, int bits); // 将数的二进制位向左循环移动指定位
unsigned int rotate_l_2(unsigned int num, int bits);
int main(void)
{
char bstr[CHAR_BIT * sizeof(unsigned int) + 1];
printf("%d in binary is \n%s.\n", TEST_VALUE, itobs(TEST_VALUE, bstr));
printf("After rotate to the left for 4 bits, the number in binary is \n%s.\n",
itobs(rotate_l(TEST_VALUE, 4), bstr));
printf("After rotate to the left for 4 bits, the number in binary is \n%s.\n",
itobs(rotate_l_2(TEST_VALUE, 4), bstr));
return 0;
}
char *itobs(int n, char *str)
{
int sz = CHAR_BIT * sizeof(int);
for (int i = sz - 1; i >= 0; --i, n >>= 1)
str[i] = (n & 1) + '0';
str[sz] = '\0';
return str;
}
unsigned int rotate_l(unsigned int num, int bits)
{
int i;
for (i = 0; i < bits; i++) // 先保存最左侧的一位,再将数向右移动1位并或运算,如此循环
num = (num >> (CHAR_BIT * sizeof(unsigned int) - 1)) | (num << 1);
return num;
}
unsigned int rotate_l_2(unsigned int num, int bits)
{
static const int size = CHAR_BIT * sizeof(unsigned int);
bits %= size;
return (num << bits) | (num >> (size - bits));
}
输出结果:
![](https://img-blog.csdnimg.cn/img_convert/3c15380111e36b4d1c292de2621a99e3.png)
题目6
方法:直接更改结构体中的内容即可。示例代码15_6.c:
#include <stdio.h>
#include <ctype.h> // 提供 isspace() 函数
#include <string.h> // 提供 strchr() 函数
typedef unsigned int uint;
typedef struct
{
uint id : 8;
uint sz : 7;
uint at : 2;
uint b : 1;
uint i : 1;
uint u : 1;
} font;
static font ft = { 1, 12, 0, 0, 0, 0 };
const char * state[4] = { "off", "on" };
const char * alignment[7] = { "left", "center", "right" };
void eatline(void);
int get_first(void);
int get_choice(void);
void change_font(void);
void change_size(void);
void change_alignment(void);
void change_toggle(int ch);
int main(void)
{
int ch;
while ((ch = get_choice()) != 'q')
{
switch (ch)
{
case 'f':
change_font();
break;
case 's':
change_size();
break;
case 'a':
change_alignment();
break;
case 'b':
case 'i':
case 'u':
change_toggle(ch);
break;
default: fputs("Wrong!", stderr);
break;
}
putchar('\n');
}
printf("Bye!\n");
return 0;
}
void eatline(void)
{
while (getchar() != '\n')
continue;
}
int get_first(void)
{
int ch;
do
{
ch = getchar();
} while (isspace(ch));
eatline();
return ch;
}
int get_choice(void)
{
int ch;
printf("ID SIZE ALIGNMENT B I U\n");
printf("%-7u%-9u%-12s", ft.id, ft.sz, alignment[ft.at]);
printf("%-8s%-8s%-8s\n", state[ft.b], state[ft.i], state[ft.u]);
printf("f) change font s) change size a) change alignment\n");
printf("b) toggle bold i) toggle italic u) toggle underline\n");
printf("q) quit\n");
while (ch = get_first(), NULL == strchr("fsabiuq", ch))
printf("Please enter with f, s, a, b, i, u or q: ");
return ch;
}
void change_font(void)
{
int ch;
uint id;
printf("Enter font id (0-255): ");
while (scanf("%u", &id) != 1)
{
while ((ch = getchar()) != '\n')
putchar(ch);
printf(" is not a id.\n");
printf("Please enter a number such as 0, 5 or 255: ");
}
ft.id = id & 0XFF; // 确保不超过 255
}
void change_size(void)
{
int ch;
uint sz;
printf("Enter font sz (0-127): ");
while (scanf("%u", &sz) != 1)
{
while ((ch = getchar()) != '\n')
putchar(ch);
printf(" is not a size.\n");
printf("Please enter a number such as 0, 5 or 127: ");
}
ft.sz = sz & 0x7F;
}
void change_alignment(void)
{
int ch;
printf("Select alignment:\n");
printf("l) left c) center r) right\n");
while (ch = get_first(), NULL == strchr("lcr", ch))
printf("Please enter with l, c or r: ");
ft.at = (ch == 'l' ? 0 : ch == 'c' ? 1 : 2); // 理解一下
}
void change_toggle(int ch)
{
if (ch == 'b')
ft.b ^= 1;
else if (ch == 'i')
ft.i ^= 1;
else
ft.u ^= 1;
}
输出结果(经测试暂时无误):
![](https://img-blog.csdnimg.cn/img_convert/9a501bcfb35155690eb40706c15cc87d.png)
题目7
方法:用指定位代表相关状态,并操作相关位,一般是先清空相关位为零(&运算),然后放入目标位(|运算)。示例代码15_7.c:
#include <stdio.h>
#include <ctype.h> // 提供 isspace() 函数
#include <string.h> // 提供 strchr() 函数
typedef unsigned long ulong;
static ulong ft = 0x00001180; //题目初始; 0000 0000 0000 |0000 0001 |0001 100| 00| 0 | 0 | 0
//从右往左数, 第1位表示U, 第2位表示I, 第3位表示B, 第4至5位表示ALIGNMENT, 第6至第12位表示SIZE, 第13至20位表示ID
const char * state[4] = {"off", "on"};
const char * alignment[7] = {"left", "center", "right"};
void eatline(void);
int get_first(void);
int get_choice(void);
void change_font(void);
void change_size(void);
void change_alignment(void);
void change_toggle(int ch);
int main(void)
{
int ch;
while ((ch = get_choice()) != 'q')
{
switch (ch)
{
case 'f':
change_font();
break;
case 's':
change_size();
break;
case 'a':
change_alignment();
break;
case 'b':
case 'i':
case 'u':
change_toggle(ch);
break;
default: fputs("Error!", stderr);
}
putchar('\n');
}
printf("Bye!\n");
return 0;
}
void eatline(void)
{
while (getchar() != '\n')
continue;
}
int get_first(void)
{
int ch;
do
{
ch = getchar();
} while (isspace(ch));
eatline();
return ch;
}
int get_choice(void)
{
int ch;
printf("ID SIZE ALIGNMENT B I U\n");
printf("%-7lu%-9lu%-12s", (ft >> 12) & 0XFF, (ft >> 5) & 0x7F, alignment[(ft >> 3) & 0x03]);
printf("%-8s%-8s%-8s\n", state[(ft >> 2) & 1], state[(ft >> 1) & 1], state[ft & 1]);
printf("f) change font s) change size a) change alignment\n");
printf("b) toggle bold i) toggle italic u) toggle underline\n");
printf("q) quit\n");
while (ch = get_first(), NULL == strchr("fsabiuq", ch))
printf("Please enter with f, s, a, b, i, u or q: ");
return ch;
}
void change_font(void)
{
int ch;
ulong id;
printf("Enter font id (0-255): ");
while (scanf("%lu", &id) != 1)
{
while ((ch = getchar()) != '\n')
putchar(ch);
printf(" is not a id.\n");
printf("Please enter a number such as 0, 5 or 255: ");
}
id &= 0XFF, id <<= 12;
for (int i = 12; i < 20; ++i)
ft &= ~(ulong)(1 << i); //将指定位 置为零
ft |= id; //填入目标位
}
void change_size(void)
{
int ch;
ulong sz;
printf("Enter font sz (0-127): ");
while (scanf("%lu", &sz) != 1)
{
while ((ch = getchar()) != '\n')
putchar(ch);
printf(" is not a size.\n");
printf("Please enter a number such as 0, 5 or 127: ");
}
sz &= 0X7F, sz <<= 5;
for (int i = 5; i < 12; ++i)
ft &= ~(ulong)(1 << i);
ft |= sz;
}
void change_alignment(void)
{
int ch;
printf("Select alignment:\n");
printf("l) left c) center r) right\n");
while (ch = get_first(), NULL == strchr("lcr", ch))
printf("Please enter with l, c or r: ");
ft &= ~(ulong)(1 << 3), ft &= ~(ulong)(1 << 4);
ft = ft | (ch == 'c' ? (ulong)(1 << 3) : ch == 'r' ? (ulong)(1 << 4) : 0);
}
void change_toggle(int ch)
{
if (ch == 'b')
{
if (ft & 0x04)
ft &= ~(ulong)(0x04);
else
ft |= (ulong)(0x04);
}
else if (ch == 'i')
{
if (ft & 0x02)
ft &= ~(ulong)(0x02);
else
ft |= (ulong)(0x02);
}
else
{
if (ft & 0x01)
ft &= ~(ulong)(0x01);
else
ft |= (ulong)(0x01);
}
}
输出结果:
![](https://img-blog.csdnimg.cn/img_convert/a840352ff0f3ec0d618446cd1ea3a3fb.png)