用法: 关闭位(清空位)
假设mask只有1号位为1
flags = flags & ~mask;
mask中为1的位都被设置清空
简化形式:
flags &= ~mask;
用法: 切换位
使用按位异或运算符。如果mask 为1, 1^ mask 为0, 0^mask为1.
(00001111) ^ (10110110)
// 结果为
(10111001)
用法: 检查位的值
if ((flags & mask) == mask)
puts("Wow");
如果mask对应的位上为1, 则打印wow。
移位运算符
- 左移 :<<
- 右移: >>
/* 位操作显示二进制*/
#include "ctest.h"
#include <stdio.h>
#include <limits.h> //提供CAHR_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-numric 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;
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(' ');
}
}
limits.h 中CAHR_BIT 宏表示char中的位数
CHAR_BIT * sizeof(int) 表示int类型的位数
切换一个值中的后n位
使用^组合掩码和待切换的值, 即可切换该值的最后n位, 其他位不变。
int invert_end (int num, int bits)
{
int mask = 0;
int bitval = 1;
while (bits-- > 0)
{
mask |= bitval;
bitval <<= 1;
}
return num ^ mask;
}
mask的后n位在循环中被设置为1, 最后num ^ mask运算即的所需结果。
#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 bin_str[CHAR_BIT * sizeof(int) + 1];
int number;
puts("enter integers and see them in binary .");
puts("Non-numric 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;
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 num, int bits)
{
int mask = 0;
int bitval = 1;
while (bits-- > 0)
{
mask |= bitval;
bitval <<= 1;
}
return num ^ mask;
}
位字段(bit field)
位字段是一个unsigned int 或signed int 类型变量中一组相邻的位。
位字段通过一个结构声明来建立:
struct{
unsigned int autfd: 1;
unsigned int bldfc: 1;
unsigned int undln: 1;
unsigned int itals: 1;
}prnt;
prnt中包含4个1位的字段, 变量prnt被储存在int大小的单元中。
要确保所赋的值不超过字段可容纳的范围。
位字段是一种更紧凑的储存数据的方式。
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;
};
c以unsigned int作为位字段结构的基本布局单元.
#include <stdio.h>
#include <limits.h>
#include <stdbool.h>
#include <stdbool.h>
/*线的样式*/
#define SOLTD 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 WHITH (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)
{
struct box_props box = { true, YELLOW, true, GREEN, DASHED };
printf("Original box settings:\n");
show_settings(&box);
box.opaque = false;
box.border_color = MAGENTA;
box.border_style = SOLTD;
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 SOLTD: printf("solid.\n"); break;
case DOTTED: printf("dotted\n"); break;
case DASHED: printf("dashed\n"); break;
default: printf("unknown type.\n"); break;
}
}
位字段和按位运算符
通过一个联合把结构方法和位方法放在一起
union Views
{
struct box_props st_view;
unsigned short us_view;
};
#include <stdio.h>
#include <limits.h>
#include <stdbool.h>
#include <stdbool.h>
/*线的样式*/
#define SOLTD 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 WHITH (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
{
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)
{
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;
box.us_view |= (FILL_BLUE | FILL_GREEN);
box.us_view ^= OPAQUE;
box.us_view |= BORDER_RED;
box.us_view &= ~STYLE_MASK;
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 SOLTD: printf("solid.\n"); break;
case DOTTED: printf("dotted\n"); break;
case DASHED: printf("dashed\n"); break;
default: printf("unknown type.\n"); break;
}
}
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_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("unknown type.\n"); break;
}
printf("The border color is %s.\n", colors[(us >> 9) & 07]);
}
warning:vs上操作失败, 不推荐对字段进行位操作运算
对齐特性(c11)
_Alignof运算符给出一个类型的对齐要求,
size_t d_align = _Alignof(float);
若d_align 值为4, 即要求float类型的对齐要求是4, 一般对齐值都应该是2的非负整数次幂, 较大的对齐值称为stricter或stronger, 较小的对齐值称为waker。
可以使用_Alignas指定一个变量或类型的对齐值
_Alignas(double) char c1;
_Alignas(8) char c2;
unsigned char _Alignas(long double) c_arr[sizeof(long double)];
#include <stdio.h>
#include <stdlib.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 aligment: %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);
}
double对齐值为8, 其地址的类型对齐可以被8整除。
由于windows堆的特性, Windows不支持c11在stdlib.h中添加的对于动态对齐的内存的内存分配函数
void *aligned_alloc(size_t aligment, size_t size);
建议使用
void * _aligned_malloc(
size_t size,
size_t alignment
);
参数size为所需的字节数, 其值应该是aligment的整数倍, aligment代表指定的对齐, 同样, 要使用free()来释放内存。