文章目录
C语言梦开始的地方3
上一章节C语言梦开始的地方2 我们了解C语言用于存储生活中的各种数据的类型,整数类型,字符类型,浮点数类型等这些。本章节我们了一下C语言提供各种的操作符,是如何使用。
算术操作符
在我们日常写代码的时候,一定是会涉及计算的
C语言为了方便运算提供了一系列的操作符,其中有一组操作符叫:算术操作符。分别是:
+ - * / %,这些操作符都是双目操作符。双目操作符的意思就是要有两个操作数比如:c = a + b; 那么当前的操作数就是a和b这两个变量。
加、减、乘、除、取余。整数除会截断,% 只能用于整数。
c
int main()
{
int a = 3,b = 2;
printf("加法操作:%d\n",a + b);
printf("减法操作:%d\n",a - b);
printf("乘法操作:%d\n",a * b);
printf("除法操作:%d\n",a / b);
printf("取余操作:%d\n",a % b);
return 0;
}
- 这里我们需注意的是%的两个操作数一定要是整数,如果是非整数就会报错。
- 不要用
unsigned进行小-大这种操作除了是你代码需要这样,因为unsigned小-大出现的数并不是负数,小-大是一个很大的数比如:2 - 3在unsigned的结果是4294967295d。但是有的人进行这个操作时得出的结果和signed的2 - 3是一样的,是因为你使用的printf格式符是signed而不是unsigned的,signed是%d,%ld这种unsigned是:%u这样printf输出的才是正确计算的值。- C99 起整数除法是向零取整(截断)。正数时两者相同(3/2=1),但负数不同:C 中 -3/2 是 -1,向下取整则是 -2。建议改成"截断小数部分/向零取整"。顺带可补充:% 取余结果的符号与被除数相同,-3 % 2 = -1。
位操作符
我们知道计算机存储的是二进制即0和1,而位操作符就是C语言提供给我们来进行二进制运算的。
分别是
& | ^ >> << ~
c
int main()
{
int a = 2, b = 3; // 2 = 010, 3 = 011
printf("a & b = %d\n", a & b); // 010 & 011 = 010 = 2
printf("a | b = %d\n", a | b); // 010 | 011 = 011 = 3
printf("a ^ b = %d\n", a ^ b); // 010 ^ 011 = 001 = 1
// 对 a 按位取反(注意 ~ 是单目操作符)取反就是0取1,1取0
printf("~a = %d\n", ~a);
printf("a << 1 = %d\n", a << 1); // 010 左移1位 = 100 = 4
printf("a >> 1 = %d\n", a >> 1); // 010 右移1位 = 001 = 1
return 0;
}
注意 : ~2 在 %d 下输出 -3(int 按补码对含符号位取反)。但是这是signed而unsigned取反是0转1,1转0的操作。计算机的计算是通过原码,反码和补码进行的后面我们会深入了解
现在我们只需要了解signed的原码左边第一个是符号位;
正数的原码,反码和补码是一样的;
负数的原码取反是反码,反码 + 1是补码
赋值操作符
C语言提供的赋值操作符有:=和复合赋值比如:+=,-=这种
注意:在变量创建的时候给一个初始值叫初始化,在变量创建好后,再给一个值,这叫赋值。
c
int main()
{
//初始化:在变量创建的同时赋初值
int a = 10;
//赋值:先创建变量,之后再给它赋值
int b;
b = 10;
//======== 复合赋值 与 普通赋值 的对比 ========
a = 10; // 重置
b = 2;
a += b; // 等价于 a = a + b;
printf("a += b => %d\n", a);
a = 10;
a -= b; // 等价于 a = a - b;
printf("a -= b => %d\n", a);
a = 10;
a *= b; // 等价于 a = a * b;
printf("a *= b => %d\n", a);
a = 10;
a /= b; // 等价于 a = a / b;
printf("a /= b => %d\n", a);
a = 10;
a %= b; // 等价于 a = a % b;
printf("a %%= b => %d\n", a);
a = 1;
a <<= b; // 等价于 a = a << b; 即 1<<2 = 4
printf("a <<= b => %d\n", a);
a = 16;
a >>= b; // 等价于 a = a >> b; 即 16>>2 = 4
printf("a >>= b => %d\n", a);
a = 5;
a &= b; // 等价于 a = a & b; 即 101 & 010 = 0
printf("a &= b => %d\n", a);
a = 5;
a |= b; // 等价于 a = a | b; 即 101 | 010 = 111 = 7
printf("a |= b => %d\n", a);
a = 5;
a ^= b; // 等价于 a = a ^ b; 即 101 ^ 010 = 111 = 7
printf("a ^= b => %d\n", a);
return 0;
}
单目操作符
前面介绍的操作符都是双目操作符(除了~),有2个操作数的。C语言中还有一些操作符只有一个操作数,被称为单目操作符。++、--、+(正)、-(负) 就是单目操作符的。
- 和 -在C语言中是符号位的意思比如:+10 等价于 10,-10 就是负数10
++ 和 -- 也分前置和后置,我们通过代码来进行了解
c
int main()
{
// 前置++ 和 后置++的区别
int i = 3;
printf("i++ = %d, 之后 i = %d\n", i++, i); // i++ 先用后加:3
int j = 3;
printf("++j = %d, 之后 j = %d\n", ++j, j); // ++j 先加后用:4
// 谭浩强 《C语言程序设计》中对++的错误使用
i = 5, j = 5;
int p, q;
p = (i++) + (i++) + (i++);
q = (++j) + (++j) + (++j);
printf("%d, %d, %d, %d\n", p, q, i, j); // 书里写的结果是 15, 22, 8, 8
// C语言对应的标准用法
i = 5; j = 5;
i++; i++; i++; // 等价于原例中的 (i++)+(i++)+(i++)
p = i; // p = 8
++j; ++j; ++j; // 先自增
q = j; // q = 8
printf("%d, %d, %d, %d\n", p, q, i, j); // 任何编译器都输出 8, 8, 8, 8
return 0;
}
虽然谭浩强老师写的代码在如今的编译器中存在二义性,但是谭浩强老师在《C语言程序设计》中的思路与套路依旧能打,主要还是谭浩强老师在写这本书时年纪已经很大了。而且这本书在如今的ai时代是一本完全可以作为入门级的C语言书籍来看的。
强制类型转换
在操作符中还有一种特殊的操作符是强制类型转换。
强制类型转换我们通过下面代码进行了解强制类型转换的用法:
- (类型)变量
c
int main()
{
int a = 3, b = 2;
// 不转:3/2 得 1;强制把 a 转 float 再除,结果 1.5
printf("%f\n", (float)a / b);
double d = 3.99;
int e = (int)d; // 截断小数部分:e = 3,不是四舍五入
printf("%d\n", e);
int f = 65;
char g = (char)f; // 65 是 'A' 的 ASCII 码
printf("%c\n", g);
// 强制转换只产生临时值,原变量 a 的类型和值不变
printf("%d\n", a); // 仍是 3
return 0;
}
隐式转换:int + float 时 int 自动提升为 float。这里提升是因为float能表达的范围更精确
显式转换语法 (类型)表达式,如 (float)a。
注意:(int)3.99 是截断不是四舍五入;double→int 大数会溢出;(float)a / b 等价 ((float)a) / b,括号位置要看清楚。
俗话说,
强扭的瓜不甜,我们使用强制类型转换都是万不得已的时候使用,如果不需要强制类型转化就能实现代码,这样自然更好的。
本章我们把 C 语言最基础的"算账工具"都过了一遍------算术、位运算、赋值、单目、强制类型转换。其实操作符不难,难的是细节:整数除法会截断、% 只能用在整数上、unsigned 不能随便小减大、~ 和补码的关系、强制转换要小心截断和丢失。
但是本章节仍有一些操作符没有介绍到,下一章节我们就配套这选择和循环语句进行讲解。
完