怎么管理网站的内容吗,云主机网站的空间在哪里,建设网站需要什么软件下载,北京专业网站制作技术博客主页#xff1a;算法歌者本篇专栏#xff1a;[C]您的支持#xff0c;是我的创作动力。 文章目录 0、总结1、操作符的分类2、二进制和进制转换2.1、2进制转10进制2.2、10进制转2进制2.3、2进制转8进制和16进制 3、原码、反码、补码4、移位操作符4.1 左移操作符4.2 右移操…博客主页算法歌者本篇专栏[C]您的支持是我的创作动力。 文章目录 0、总结1、操作符的分类2、二进制和进制转换2.1、2进制转10进制2.2、10进制转2进制2.3、2进制转8进制和16进制 3、原码、反码、补码4、移位操作符4.1 左移操作符4.2 右移操作符4.3 警告不要移动负数位 5、位操作符5.1 例1观察位操作符5.2 例2不能创建临时变量第三个变量实现两个数的交换。5.3 例3求一个整数存储在内存中的二进制中1的个数。5.4 例4如何判断一个数是否是2的次方数5.5 例5二进制位置0或者置1 6、逗号表达式7、下标访问[]、函数调用()8、结构成员访问操作符9、操作符的属性优先级、结合性10、其他10.1 整型提升10.2 算术转换 0、总结 1、操作符的分类
算术操作符、-、*、/、%移位操作符、位操作符、|、^、~赋值操作符、、-、*、/、%、、、、|、^单目操作符!、、--、取地址操作符、*解引用操作符、正号操作符、-负号操作符、~、sizeof、(类型)关系操作符、、、、、!逻辑操作符、||条件操作符?:逗号表达式,下标引用[]函数调用()结构成员访问.、-
操作符中一些操作符和二进制有关系需要先简单了解二进制和进制转换的知识。
2、二进制和进制转换
进制是数值的不同表示形式。例如数值15的各种进制的表示形式
15的2进制 1111
15的8进制 17
15的10进制15
15的16进制F观察10进制得出规律如下
10进制中满10进1。10进制的数字每一位都是0~9的数字组成。
那么二进制也是一样的
2进制中满2进1。2进制的数字每一位都是0~1的数字组成。
2.1、2进制转10进制
在10进制中每一位是权重10进制的数字从右向左是个位、十位、百位…分别每一位的权重是100101102…。
在十进制中如图 假设2进制的1101如何理解呢如图 2.2、10进制转2进制
从图中可以知道余数作用是求出是当前数的个位。 2.3、2进制转8进制和16进制
原理二进制数可以按照3个位数或更一般地按照任意固定数量的位数转换到其他进制这是基于进制转换的基本原理和方便性考虑的。
在8进制中8进制的数字每一位是0 ~ 7的0 ~ 7的数字各自写成2进制最多有3个2进制位就足够了。所以2进制转8进制数的时候从2进制序列中右边低位开始向左每3个2进制位会换算一个8进制位剩余不够3个2进制位的直接换算。
注意0开头的数字会被当做8进制。 在16进制中16进制的数字每一位是0 ~ 9、a ~ f的0 ~ 9、a ~ f的数字各自写成2进制最多有4个2进制就足够了。比如f的二进制1111所以在2进制转16进制数的时候从2进制序列中右边低位开始向左每4个2进制位会换算一个16进制位剩余不够4个二进制位的直接换算。
注意16进制表示的时候前面加0x。
例如2进制的01101011换成16进制0x6b。 进制转换总结如下
二进制转八进制3位二进制二进制转十进制权和计算法二进制转十六进制4位二进制十进制转十六进制先转二进制之后转十六进制
#include stdio.h
int main()
{printf(%d\n, 153); // 十进制printf(%d\n, 0153); // 八进制printf(%d\n, 0x153); // 十六进制return 0;
}输出
153
107
3393、原码、反码、补码
二进制
整数的2进制表示方法原码、反码、补码。有符号整数的2进制三种表示方法均有符号位和数值位两部分。2进制序列中最高位的1位是被当做符号位剩余都是数值位。在符号位中0表示“正”1表示“负”。原码直接将数值按照正负数的形式翻译成二进制得到的就是原码。反码将原码的符号位不变其他位依次按位取反就可以得到反码。补码反码1就得到补码。正整数的原、反、补码都相同。负整数的三种表示方法各不相同。
值得一提是
反码得到原码也是可以使用取反1的操作。 对整形来说数据存放内存中其实存放的是补码对于整数的计算统一都是用补码来计算。
为什么呢 在计算机系统中数值一律用补码来表示和存储。原因在于使用补码可以将符号位和数值域统一处理 同时加法和减法也可以统一处理CPU只有加法器此外补码与原码相互转换其运算过程是相同的不需要额外的硬件电路。 #include stdio.h
int main()
{int a -10;// -10是存放在a中a是整型变量是4个字节32bit位// 10000000 00000000 00000000 00001010 - 原码// 11111111 11111111 11111111 11110101 - 反码// 11111111 11111111 11111111 11110110 - 补码int b 10;// 00000000 00000000 00000000 00001010 - 原码// 00000000 00000000 00000000 00001010 - 反码// 00000000 00000000 00000000 00001010 - 补码return 0;
}4、移位操作符
左移操作符
右移操作符
注意移位操作符的操作数只能是整数。
4.1 左移操作符
移位规则左边抛弃、右边补0。 #include stdio.h
int main()
{int num 10;// 移位规则左边抛弃、右边补0int n num 1;printf(n %d\n, n);printf(num %d\n, num);return 0;
}输出
n 20
num 104.2 右移操作符
移位规则首先右移运算符分两种
1、逻辑右移左边用0填充右边丢弃。2、算术右移左边用原该值的符号位填充右边丢弃。最常见 注意右移采取逻辑右移还是算术右移取决于编译器的实现常见的编译器都是算术右移。
#include stdio.h
int main()
{int num 10;// 移位规则左边用原该值的符号位填充右边丢弃。int n num 1;printf(n %d\n, n);printf(num %d\n, num);return 0;
}输出
n 5
num 104.3 警告不要移动负数位
对于移位运算符不要移动负数位这个是标准未定义的。
例如
int num 10;
num -1; //error5、位操作符
位操作符有
按位与| 按位或^按位异或~按位取反
注意他们的操作数必须是整数。
5.1 例1观察位操作符
#include stdio.h
int main()
{// 10000000 00000000 00000000 00000011 -3的原码// 11111111 11111111 11111111 11111100// 11111111 11111111 11111111 11111101 -3的补码int num1 -3;// 00000000 00000000 00000000 00000101 5的补码int num2 5;// 00000000 00000000 00000000 00000101 按位与得出5printf(%d\n, num1 num2);// 11111111 11111111 11111111 11111101 按位或补码// 10000000 00000000 00000000 00000011 计算反码1得出-3printf(%d\n, num1 | num2);// 11111111 11111111 11111111 11111000 按位异或补码// 10000000 00000000 00000000 00001000 计算反码1得出-8printf(%d\n, num1 ^ num2);// 00000000 00000000 00000000 00000000 0的补码// 11111111 11111111 11111111 11111111 ~0// 10000000 00000000 00000000 00000001 计算反码1得出-1printf(%d\n, ~0);return 0;
}输出
5
-3
-8
-15.2 例2不能创建临时变量第三个变量实现两个数的交换。
#include stdio.h
int main()
{int a 100;int b 202;a a ^ b;b a ^ b;a a ^ b;printf(a %d b %d\n, a, b);return 0;
}输出
a 202 b 1005.3 例3求一个整数存储在内存中的二进制中1的个数。
方法1
// 方法1
#include stdio.h
int main()
{int num 0;scanf(%d, num);int count 0;while (num){if (num % 2 1)count;num num / 2;}printf(%d\n, count);return 0;
}在负数中方法1失效了比如-1在内存中1的个数有有32而结果是0。
继续优化写方法2
// 方法2
#include stdio.h
int main()
{int num 0;scanf(%d, num);int count 0;for (int i 0; i 32; i){if (num (1 i))count;}printf(%d\n, count);return 0;
}方法2中是必须循环32次再继续优化写方法3
// 方法3
#include stdio.h
int main()
{int num 0;scanf(%d, num);int count 0;while (num){count;num num (num - 1); }printf(%d\n, count);return 0;
}在方法3中每次循环都会将 num 的最低位的1清零并将计数器 count 加1。
5.4 例4如何判断一个数是否是2的次方数
if (n (n - 1) 0)
{n就是2的次方数
}5.5 例5二进制位置0或者置1
编写代码将13二进制序列的第5位修改为1然后再改回0。
13的2进制序列 00000000 00000000 00000000 00001101
将第5位置为1后 00000000 00000000 00000000 00011101
将第5位再置为0 00000000 00000000 00000000 00001101代码如下
#include stdio.h
int main()
{int a 13;a a | (1 4);printf(a %d\n, a);a a ~(1 4);printf(a %d\n, a);return 0;
}6、逗号表达式
逗号表达式就是用逗号隔开的多个表达式从左向右依次执行整个表达式的结果是最后一个表达式的结果。
exp1, exp2, exp3, ... expN7、下标访问[]、函数调用()
下标引用操作符操作数为一个数组名 一个索引值。
int arr[10]; // 创建数组
arr[9] 10; // 使用下标引用操作符
[ ] 的两个操作数是arr和9。函数调用操作符接受一个或者多个操作数第一个操作数是函数名剩余的操作数就是传递给函数的参数。
8、结构成员访问操作符
点操作符.直接访问结构体成员点操作符接受两个操作数。
使用方式结构体变量.成员名。如下
#include stdio.h
struct Point
{int x;int y;
}p { 1,2 };int main()
{printf(x%d, y%d\n, p.x, p.y);return 0;
}运行
x1, y2箭头操作符-间接访问结构体成员。 有时候我们得到的不是⼀个结构体变量而是得到了一个指向结构体的指针。
使用方式结构体指针-成员名。如下
#include stdio.h
struct Point
{int x;int y;
}p { 1,2 };int main()
{struct Point* ptr p;ptr-x 10;ptr-y 20;printf(x%d, y%d\n, ptr-x, ptr-y);return 0;
}运行
x10, y209、操作符的属性优先级、结合性
C语⾔的操作符有2个重要的属性优先级、结合性这两个属性决定了表达式求值的计算顺序。
结合性如果两个运算符优先级相同优先级没办法确定先计算哪个了这时候就看结合性了则根据运算符是左结合还是右结合决定执行顺序。大部分运算符是左结合从左到右执行少数运算符是右结合从右到左执行比如赋值运算符 。
建议大概记住这些操作符的优先级就行其他操作符在使用的时候查看下面表格就可以了。
• 圆括号()
• 自增运算符自减运算符--
• 单⽬运算符和-
• 乘法*除法/
• 加法减法-
• 关系运算符、等
• 赋值运算符 官方文档https://zh.cppreference.com/w/c/language/operator_precedence
10、其他
10.1 整型提升
C语言中整型算术运算总是至少以缺省整型类型的精度来进行的。
缺省在计算机科学和相关领域中它通常指的是“默认”或“预设”的意思。
整型提升为了获得这个精度表达式中的字符和短整型操作数在使用之前被转换为普通整型。
整型提升的意义 表达式的整型运算要在CPU的相应运算器件内执行CPU内整型运算器(ALU)的操作数的字节长度一般就是int的字节长度同时也是CPU的通用寄存器的长度。因此即使两个char类型的相加在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度。 通用CPUgeneral-purposeCPU是难以直接实现两个8比特字节直接相加运算虽然机器指令中可能有这种字节相加指令。所以表达式中各种长度可能小于int长度的整型值都必须先转换为int或unsigned int然后才能送入CPU去执行运算。 char a, b, c;
...
a b c;b和c的值被提升为普通整型然后再执行加法运算。加法运算完成之后结果将被截断然后再存储于a中。
如何进行整体提升呢
有符号整数提升是按照变量的数据类型的符号位来提升的。无符号整数提升高位补0。
// 负数的整形提升
char c1 -1;
整型提升
11111111 11111111 11111111 11111111
// 正数的整形提升
char c2 1;
整型提升
00000000 00000000 00000000 0000000110.2 算术转换
如果某个操作符的各个操作数属于不同的类型那么除非其中一个操作数的转换为另一个操作数的类型否则操作就无法进行。下面的层次体系称为寻常算术转换。
long double
double
float
unsigned long int
long int
unsigned int
int如果某个操作数的类型在上面这个列表中排名靠后那么首先要转换为另外一个操作数的类型后执行运算。 完。