1.位操作

* 置1    使用 |
* 清0    使用&
* 取反   使用^ #include <stdio.h> int main(void) { // 把一个寄存器值的bit4~bit7取反,其他位不变
unsigned int a = 0x123d0c37; unsigned int b = 0xf0; unsigned int c; c = a ^ b;
printf("a & b = 0x%x.\n", c);//0x123d0cc7. /* // 把一个寄存器值的bit4~bit7置1,其他位不变
unsigned int a = 0x123d0cd7; unsigned int b = 0xf0; unsigned int c; c = a | b;
printf("a & b = 0x%x.\n", c); */ /* // 把一个寄存器值的bit13~21清0,其他位不变 unsigned int a
= 0x123d0c57; unsigned int b = 0xffc01fff; unsigned int c; c = a & b; printf("a
& b = 0x%x.\n", c); // 0x12000c57. */ }
使用宏对变量a的bit n 位进行置位,清0,取反操作

假设有一个整数为x,编写三个将x的二进制位的第n位置1、清零、取反,其他位不变。

1.清零

如有x=10,二进制表示为:

00000000 00000000 00000000 00001010,二进制位的最右边称为第一位,比如将第二位的1清为0,则为:

00000000 00000000 00000000 00001000 = 8,

将第三位置为1,则为:   00000000 00000000 00000000 00001110 = 14。

将第一位取反,则为:   00000000 00000000 00000000 00001011 = 11。
#include <iostream> using namespace std; #define IBS(n) 0x01<<(n-1) void
Set_N_To_1(int &x, int n) { x |= IBS(n); } void Clear_N_To_0(int &x, int n) { x
&= ~IBS(n); } void Negate_N(int &x, int n) { x ^= IBS(n); } int main() { int x
= 10; Set_N_To_1(x, 3); cout<<x<<endl; x = 10; Clear_N_To_0(x, 2);
cout<<x<<endl; x = 10; Negate_N(x, 1); cout<<x<<endl; return 0; } #include
<iostream> using namespace std; #define Clear_N_To_0(x, n) (x & (~(1 <<
(n-1)))) #define Set_N_To_1(x, n) (x | (1 << (n-1))) #define Negate_N(x, n) (x
^ (1 << (n-1))) int main() { cout << Clear_N_To_0(10, 2) << endl; cout <<
Set_N_To_1(10, 3) << endl; cout << Negate_N(10, 1) << endl; return 0; }
注宏定义中的n-1,只是为了更好理解,比如第一位置就是Set_N_To_1(x, 1),从下标1开始计数

2.strcpy() 函数 标准实现

C语言标准库函数  
原型声明:extern char* strcpy(char *dst,const char *src); 
  头文件:string.h 
  功能:把src所指由NULL结束的字符串复制到dst所指的数组中。 
  说明:src和dst所指内存区域不可以重叠且dst必须有足够的空间来容纳src的字符串。 
  返回指向dst的指针。 

     strcpy函数将str拷贝至输出参数dst中,同时函数的返回值又是dst。这样做并非多此一举,可以获得如下灵活性:   
char str[20]; int length = strlen( strcpy(str, “Hello World”) );
    作用:为了生成链式表达式。
/* C语言标准库函数strcpy的一种典型的工业级的最简实现 返回值: 返回目标串的地址。
对于出现异常的情况ANSI-C99标准并未定义,故由实现者决定返回值,通常为NULL。 参数: 目标串 dest 源串 str */ char*
strcpy(char* dst, const char* str) { //1.断言 assert(dst != NULL && str != NULL);
//2.使用ret指向dst字符串 char* ret = dst; //3.复制 while(*str != '\0') { *dst = *str;
src++; dst++; } *dst = '\0'; return ret; }
注意:

* 输入参数 const
* 对源地址和目的地址加非0断言
* 为了实现链式操作,将目的地址返回
3.strcat() 函数 标准实现
//把src所指向的字符串追加到 dst 所指向的字符串的结尾。 char* strcat(char* dst, const char* str) {
//1.使用指针指向dst字符串 char* ret = dst; //2.移动指针到dst字符串的末尾 while(*ret) ret++; //3.拼接
while(*src != '\0') { *ret++ = *str++; } *ret = '\0'; return dst; }
4.strcmp()函数 标准实现

把 str1 所指向的字符串和 str2 所指向的字符串进行比较。

int strcmp(const char *str1, const char *str2)
参数
str1 -- 要进行比较的第一个字符串。
str2 -- 要进行比较的第二个字符串。
返回值
该函数返回值如下:

如果返回值 < 0,则表示 str1 小于 str2。
如果返回值 > 0,则表示 str2 小于 str1。
如果返回值 = 0,则表示 str1 等于 str2。
//把 str1 所指向的字符串和 str2 所指向的字符串进行比较。 int strcmp(const char *str1, const char
*str2) { int ret = 0; while( !(ret = *(unsigned char*)str1 - *(unsigned
char*)str2) && *str1) { str1++; str2++; } if( ret < 0 ) { return -1; } else if(
ret > 0 ) { return 1; } return 0; }
5.strstr()函数 标准实现

char* strstr(const char *s1, const char *s2) 

返回值:若s2是s1的子串,则返回s2在s1的首次出现的地址;如果s2不是s1的子串,则返回NULL。
char* strstr(const char* s1, const char* s2) { int len2; if( !(len2 =
strlen(s2)) )//此种情况下s2不能指向空,否则strlen无法测出长度,这条语句错误 { return (char*)s1; } for( ;
*s1; ++s1) { if( *s1 == *s2 && strncmp(s1, s2, len2) == 0) return (char*)s1; }
return NULL; }
6.TCP协议如何保证可靠性?

(1)TCP在传输有效信息前要求通信双方必须先握手,建立连接才能通信
(2)TCP的接收方收到数据包后会ack给发送方,若发送方未收到ack会丢包重传
(3)TCP的有效数据内容会附带校验,以防止内容在传递过程中损坏
(4)TCP会根据网络带宽来自动调节适配速率(滑动窗口技术)
(5)发送方会给各分割报文编号,接收方会校验编号,一旦顺序错误即会重传。

技术
©2019-2020 Toolsou All rights reserved,
vue项目中使用本地静态JS数据文件利用克鲁斯卡尔算法求最小生成树C++ 移动构造函数和拷贝构造函数华为鸿蒙 HarmonyOS 2 正式发布VS添加动态链接库的两种方法python_樱花树Jmeter配置元件之HTTP授权管理器与 HTTP缓存管理器-19vue+element-ui里面table组件多选框实现批量操作RISC-V指令集架构特点及其总结js实现上下文菜单