[声明]:本文章为博主自学C语言时遇到的困惑,如有不正,欢迎指出
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
//A_算术操作符 '+', '-', '*', '/', '%'
int main(void) {
//'/'左右 两个 操作数都为 整数 -> 整数乘法
int a = 6 / 5;
printf("%d\n", a);//1
float b = 6 / 5;
printf("%f\n", b);//1.000000
//'/'至少 一个 操作数为 浮点数 -> 浮点数除法
float c = 6.0 / 5;
printf("%f\n", c);//1.200000
//'%'(取模操作符)的操作数必须为 整数
return 0;
}
//B_整数的二进制表示形式(原码&&反码&&补码)
int main(void) {
//原码:根据数值得出 二进制序列
//反码:保留原码的 符号位,其它位 按位取反
//补码:反码 + 1
//负数 在 内存 中保存为 二进制的 补码
//对于 正整数,原码&&反码&&补码 相同
//使用补码的好处
int a = 3;//00000000 00000000 00000000 00000011
int b = -3;
//-3的二进制序列10000000 00000000 00000000 00000011
//此时 a + b = 3 + (-3) = 0
//但是 a 与 b 的 二进制序列相加 等于 -6 != 0
//10000000 00000000 00000000 00000110
//-3的反码11111111 11111111 11111111 11111100
//-3的补码11111111 11111111 11111111 11111101
//a 的 二进制序列 与 b 的 补码相加 等于 0
//00000000 00000000 00000000 00000000
//左边溢出的一位 1 被舍弃
return 0;
}
//C_移位操作符 '<<', '>>'
int main(void) {
//'<<'(左移操作符),将操作数的 二进制位 左移(左丢弃,右补0)
int a = 2;//a = 00000000 00000000 00000000 00000010
int b = a << 1;//b = 00000000 00000000 00000000 00000100
printf("b = %d\n", b);
//移位操作符 不会 改变 操作数,生效的是 返回值
printf("a = %d\n", a);//2
//'>>'(右移操作符),将操作数的 二进制位 右移(逻辑右移&&算术右移)
//逻辑右移(右丢弃,左补0)
int c = 10;//a = 00000000 00000000 00000000 00001010
int d = c >> 1;//b = 00000000 00000000 00000000 00000101
printf("d = %d\n", d);
//算术右移(右丢弃,左补符号位)->本编译器选择的方式
int e = -1;//a = 11111111 11111111 11111111 11111111
int f = e >> 1;//b = 111111111 11111111 11111111 11111111
printf("f = %d\n", f);//-1
return 0;
}
//D_位(2进制)操作符 '&', '|', '^'
int main(void) {
//位操作符的操作数为 整数
//'&'(按位与),只要有 一位 为0则为0,只有 两位 全为1才为1
int a = 3;//00000000 00000000 00000000 00000011
int b = 5;//00000000 00000000 00000000 00000101
int c = a & b;//00000000 00000000 00000000 00000001
printf("c = %d\n", c);//1
//'|'(按位或),只要有 一位 为1则为1,只有 两位 全为0才为0
int d = a | b;//00000000 00000000 00000000 00000111
printf("d = %d\n", d);//7
//'^'(按位异或),两位不同则为1,两位相同则为0
int e = a ^ b;//00000000 00000000 00000000 00000110
printf("e = %d\n", e);//6
//位操作符的应用
//交换两个变量的值,不使用多余变量
printf("a = %d, b = %d\n", a, b);//3,5
a = a ^ b;//00000000 00000000 00000000 00000110
b = a ^ b;//00000000 00000000 00000000 00000011
a = a ^ b;//00000000 00000000 00000000 00000101
printf("a = %d, b = %d\n", a, b);//5,3
//求一个整数的二进制序列有多少位1
int num = 0;
int count = 0;
printf("输入一个整数:");
scanf("%d", &num);
for (int i = 0; i < 32; i++) {
if (1 & (num >> i)) {
count++;
}
}
printf("%d 的二进制序列有 %d 位 1\n", num, count);
//13,3
//-1,32
return 0;
}
//E_赋值操作符(直接赋值操作符&&复合赋值操作符) '='
//F_单目操作符(与双目操作符对照) '!', '-', '+', 'sizeof', '~', '--', '++', '&', '*', '(ElemType)'
int main(void) {
//'!'(逻辑取反)
//'-'&&'+'(负值&&正值)
//'sizeof'(操作数的类型长度,返回单位Bytes)
//'sizeof'不是 函数
//'sizeof'内的表达式不参与运算
//'sizeof'的计算在 编译 阶段就已完成
int a = 5;
printf("sizeof a = %lld\n", sizeof a);//5
printf("sizeof(a) = %lld\n", sizeof(a += 5));//4
printf("a = %d\n", a);//5
//'~'(对一个数的二进制序列按位取反,包括符号位)
int b = -1;//补码11111111 11111111 11111111 11111111
printf("~b = %d\n", ~b);//0
//'--'&&'++'
printf("a = %d\n", a);//5
printf("b = %d\n", b);//-1
//后置 -> 先取值,再生效
a = b++;
printf("a = %d\n", a);//-1
printf("b = %d\n", b);//-1 + 1 = 0
//前置 -> 先生效,再取值
a = ++b;
printf("a = %d\n", a);//0 + 1 = 1
printf("b = %d\n", b);//0 + 1 = 1
//'&'(取地址)&&'*'(解引用)
int* pa = &a;
printf("Website of a = %p\n", &a);//0000000E804FF964
*pa = 10;
printf("a = %d\n", a);//10
//'(ElemType)'(强制类型转换)
int c = (int)3.14;
printf("c = %d\n", c);//3
return 0;
}
//G_关系操作符 '>', '<', '>=', '<=', '==', '!='
//H_逻辑操作符 '&&', '||'
int main(void) {
//'&&'(逻辑与)&&'||'(逻辑或)的 短路机制
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++ && ++b && d++;
printf("i = %d, a = %d, b = %d, c = %d, d = %d\n", i, a, b, c, d);//0,1,2,3,4
i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++ || ++b || d++;
printf("i = %d, a = %d, b = %d, c = %d, d = %d\n", i, a, b, c, d);//1,1,3,3,4
return 0;
}
//I_条件(三目)操作符 exp1 ? exp2 : exp3
int main(void) {
//若exp1为 真,则返回exp2,否则返回exp3
int a = 5;
int b = 0;
b = a > 0 ? a : b;
printf("b = %d\n", b);//5
a = 5;
b = 0;
b = a < 0 ? a : b;
printf("b = %d\n", b);//0
return 0;
}
//J_逗号表达式 exp1, exp2, exp3, ...expN
int main(void) {
//逗号表达式 从左向右 依次计算,返回 最后一个 表达式
int a = 0, b = 1, c = 2, d = 3;
a = (b += 1, c += 1, d += 1);
printf("a = %d, b = %d, c = %d, d = %d\n", a, b, c, d);//4,2,3,4
int i = 0;
int j = 0;
while (i < 10) {
i++;
j++;
}printf("j = %d\n", j);//10
i = j = 0;
while (i++, j++, i < 10) {;}
printf("j = %d\n", j);//10
return 0;
}
//K_下标引用操作符'[]'&&函数调用操作符'()'&&结构成员访问操作符'.', '->'
int main(void) {
//'[]'两个操作数 -> 数组名 && 索引值
//'()'1+多个操作数 -> 函数名 && 参数值
//'.'&&'->'
return 0;
}
//L_隐式类型转换 -> 整型提升(通用CPU的内部运算所需)&&算术转换(向长字节转换)
int main(void) {
char a = 127;//01111111
char b = 3;//00000011
char c = a + b;
//发生相加时,a与b都没有达到 int 大小,进行整型提升
//整型提升按照变量的 符号位 进行填充
//若无符号位,则填充 0
//a 经提升 = 00000000 00000000 00000000 01111111
//b 经提升 = 00000000 00000000 00000000 00000011
//int 的 a + b = 130
//a + b = 00000000 00000000 00000000 10000010
//得到的 int 计算结果 截断(后8个bit位) 装入 char 的 c 中
//char 的 c = 10000010,符号位为 1
//要以 int 打印 c,c 也需要进行整型提升,c 为 负数
//c 经提升 = 11111111 11111111 11111111 10000010 为 c 的 补码
//c 的 原码 = 取反(补码-1) = 00000000 00000000 00000000 01111110
printf("c = %d\n", c);//-126
int d = 3;
float e = 3.5;
//d + e -> d 向上转换为 float 进行运算
return 0;
}
//M_操作符的属性(优先级&&结合性&&是否控制结合顺序)