一、输入和输出
1.输出
(1)输出定义:将程序的运行结果输出到控制台或终端窗口中
(2)printf语法格式如下:
int a;
a=10;
printf("%d\n",a);
(3)printf常用的格式化占位符
| 占位符 | 对应类型 | 示例输出 | 说明 |
|---|---|---|---|
%d | int | 123 | 十进制有符号整数 |
%u | unsigned int | 123 | 十进制无符号整数 |
%hd | short / short int | 123 | short整数 |
%hu | unsigned short | 123 | 无符号short |
%ld | long | 123456 | long整数 |
%lu | unsigned long | 123456 | 无符号long |
%lld | long long | 123456789 | 超大整数 |
%llu | unsigned long long | 123456789 | 无符号超大整数 |
%c | char | A | 单个字符 |
%s | 字符串 char[] | hello | 字符串 |
%f | float | 3.14 | 浮点数输出 |
%lf | double | 3.14 | double输入常用 |
%x | 十六进制整数 | ff | 十六进制(小写) |
%X | 十六进制整数 | FF | 十六进制(大写) |
%o | 八进制整数 | 77 | 八进制 |
%p | 指针/地址 | 0x1234 | 内存地址 |
(4)printf常用的格式化占位符示例代码
#include <stdio.h>
int main() {
// 定义变量
char c = 'A';
short s = 10;
int i = 10;
long l = 10;
float f = 1.123456789123456789;
double d = 1.123456789123456789;
unsigned int ui = 20;
char *name = "bill";
// 格式化输出
// 整型
printf("c=%d\n", c);
printf("s=%hd\n", s);
printf("i=%d\n", i);
printf("l=%ld\n", l);
// 浮点类型
printf("f=%.10f\n", f);
printf("d=%.20lf\n", d);
// 无符号数据
printf("u=%u\n", ui);
// 八进制和十六进制 可以加上前缀# 自动输出八进制和十六进制0或0x
printf("o=%#o\n", 120);
printf("x=%#x\n", 120);
// 字符串类型
printf("s=%s\n", name);
// 内存地址
printf("ps=%p\n", &s);
return 0;
}
2.输入
(1)输入:接受用户输入数据的过程
(2)scanf语法格式
scanf("格式化字符串",&变量一,&变量二,......);
(格式化字符串用于指定输入的数据类型及其格式,变量1、变量2等是要读入的变量的地址)
(3)示例代码
#include <stdio.h>
int main() {
//定义int类型变量age,通过scanf输入内容,然后打印内容
int age;
printf("请输入年龄:");
scanf("%d",&age);
printf("age =%d\n",age);
return 0;
}
3.例题
(1)从键盘输入一个圆形半径,输出圆的周长和面积
(2) 思路步骤
1. 定义常量pi
2. 定义半径变量r
3. 输入半径
4. 求周长和面积, * 为乘以运算符
5. 输出周长和面积
(3)参考代码
#include <stdio.h>
int main() {
// 1.定义常量pi
const double pi = 3.1415;
// 2.定义半径变量r
double r;
// 3.输入半径
printf("请输入半径:");
scanf("%lf", &r);
// 4.求周长和面积, * 为乘以运算符
double len = 2 * pi * r;
double area = pi * r * r;
// 5.输出周长和面积
printf("周长len = %lf, 面积area = %lf\n", len, area);
return 0;
}
二、运算符
1.算术运算符
| 运算符 | 描述 | 示例 | 结果 | 说明 |
|---|---|---|---|---|
+ | 加法 | a + b | 13 | 双目运算符 |
- | 减法 | a - b | 7 | 双目运算符 |
* | 乘法 | a * b | 30 | 双目运算符 |
/ | 除法 | a / b | 3 | 整数除法截断小数;若为浮点数 10.0/3 → 3.333333 |
% | 取模(求余) | a % b | 1 | 只能用于整数,结果的符号与被除数相同 |
++ | 自增1 | a++ 或 ++a | 11 | 单目运算符,分前置(先增减后使用)和后置(先使用后增减) |
-- | 自减1 | b-- 或 --b | 2 | 单目运算符,同上 |
代码示例
#include <stdio.h>
int main() {
// 2数相除,要想得到小数的结果,分子分母必须有一个数是小数
double c = 5/2; // 5, 2个都是整数,只会取整
printf("c1 = %lf\n", c);
c = 5.0/2;
printf("c2 = %lf\n", c);
c = 5/2.0;
printf("c3 = %lf\n", c);
int i = 0;
// 前置++
// 先加后用
int b = ++i;
printf("前置:b = %d, i = %d\n", b, i);
// 后置++
// 先用后加
i = 0;
b = i++;
printf("后置:b = %d, i = %d\n", b, i);
return 0;
}
2.赋值运算符
| 运算符 | 名称 | 示例 | 等价写法 | 作用说明 |
|---|---|---|---|---|
= | 赋值运算符 | a = 5 | — | 把右边的值赋给左边变量 |
+= | 加后赋值 | a += 3 | a = a + 3 | 先相加,再赋值 |
-= | 减后赋值 | a -= 2 | a = a - 2 | 先相减,再赋值 |
*= | 乘后赋值 | a *= 4 | a = a * 4 | 先相乘,再赋值 |
/= | 除后赋值 | a /= 2 | a = a / 2 | 先相除,再赋值 |
%= | 取模后赋值 | a %= 3 | a = a % 3 | 取余数后赋值 |
<<= | 左移后赋值 | a <<= 1 | a = a << 1 | 左移位后赋值 |
>>= | 右移后赋值 | a >>= 1 | a = a >> 1 | 右移位后赋值 |
&= | 按位与后赋值 | a &= b | a = a & b | 按位与后赋值 |
|= | 按位或后赋值 | a |= b | a = a | b | 按位或后赋值 |
^= | 按位异或后赋值 | a ^= b | a = a ^ b | 按位异或后赋值 |
代码示例:
#include <stdio.h>
int main() {
int a=20;
a -= 5;
printf("%d\n",a);
return 0;
}
3.比较运算符
C 语言的比较运算中, “真”用数字“1”来表示, “假”用数字“0”来表示。且一个=代表赋值。
| 运算符 | 名称 | 示例 | 含义 | 结果 |
|---|---|---|---|---|
== | 等于 | a == b | 判断 a 是否等于 b | 相等为 1,否则为 0 |
!= | 不等于 | a != b | 判断 a 是否不等于 b | 成立为 1,否则为 0 |
> | 大于 | a > b | 判断 a 是否大于 b | 成立为 1,否则为 0 |
< | 小于 | a < b | 判断 a 是否小于 b | 成立为 1,否则为 0 |
>= | 大于等于 | a >= b | 判断 a 是否大于或等于 b | 成立为 1,否则为 0 |
<= | 小于等于 | a <= b | 判断 a 是否小于或等于 b | 成立为 1,否则为 0 |
代码示例:
#include <stdio.h>
int main() {
int a = 15;
int b = 30;
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);
printf("%d\n", a <= b);
return 0;
}
4.逻辑运算符
| 运算符 | 名称 | 示例 | 含义 | 结果规则 |
|---|---|---|---|---|
&& | 逻辑与 | a > 0 && b > 0 | 两个条件都成立 | 都为真结果才为 1 |
|| | 逻辑或 | a > 0 || b > 0 | 两个条件任意一个成立 | 有一个真结果就为 1 |
! | 逻辑非 | !(a > 0) | 条件取反 | 真变假,假变真 |
代码示例:
#include <stdio.h>
int main() {
// &&(与),可以理解为并且
// 案例:请判断班长和他女朋友是否符合法定结婚年龄
int boy = 25;
int girl = 21;
int result = boy >= 22 && girl >= 20;
printf("%d\n", result);
// ||(或),可以理解为或者
// 案例:班长女朋友玩原神没有原石了,请帮班长判断是否有足够的钱
double wx_money = 100;
double alipay_money = 300;
result = wx_money >= 398 || alipay_money >= 398 || wx_money + alipay_money >= 398;
printf("%d\n", result);
// !(非),可以理解为不是
printf("%d\n", !0);
printf("%d\n", !!1);
// 短路规则
// && 左边为假,右边不执行
// && 左边为真,右边执行
0 && printf("我是右边不执行\n");
1 && printf("我是右边不执行\n");
// || 左边为真,右边不执行
// || 左边为假,右边执行
1 || printf("我是右边不执行\n");
0 || printf("我是右边不执行\n");
return 0;
}
5.位运算符
| 运算符 | 名称 | 作用说明 | 示例 | 二进制运算过程 | 结果 |
|---|---|---|---|---|---|
& | 按位与 | 两个位都为1,结果才为1 | 5 & 3 | 0101 & 0011 = 0001 | 1 |
| | 按位或 | 两个位有一个为1,结果就为1 | 5 | 3 | 0101 | 0011 = 0111 | 7 |
^ | 按位异或 | 两个位不同为1,相同为0 | 5 ^ 3 | 0101 ^ 0011 = 0110 | 6 |
~ | 按位取反 | 0变1,1变0 | ~5 | ~00000101 = 11111010 | -6 |
<< | 左移 | 所有二进制位左移,右边补0 | 5 << 1 | 0101 → 1010 | 10 |
>> | 右移 | 所有二进制位右移 | 5 >> 1 | 0101 → 0010 | 2 |
(补充:取反、左移、右移都要在补码的基础上运算)
(1)与运算(&)
按位与(&)运算:位与位进行比较,如果都为1,则为1,否则为0
(口诀:全一为一,其余为零)
代码示例:
/*
40与15进行与运算
40转换成二进制为 0010 1000;
15转换成二进制为 0000 1111;
进行与运算:0010 1000
& 0000 1111
------------------
0000 1000 -> 8
*/
#include <stdio.h>
int main() {
printf("40 & 15 = %d\n", 40 & 15);
return 0;
}
(2)或运算(|)
按位或(|)运算:位与位进行比较,如果都为0,则为0,否则全为1
口诀:全零为零,其余为一
/*
40与15进行与运算
40转换成二进制为 0010 1000;
15转换成二进制为 0000 1111;
进行与运算:0010 1000
| 0000 1111
------------------
0010 1111 -> 47
*/
#include <stdio.h>
int main() {
printf("40 | 15 = %d\n", 40 | 15);
return 0;
}
(3)异或运算(^)
按位异或运算:位与位进行比较,不同为1,相同为0;
口诀:不同为一,相同为零。
代码示例:
/*
40与15进行与运算
40转换成二进制为 0010 1000;
15转换成二进制为 0000 1111;
进行与运算:0010 1000
^ 0000 1111
------------------
0010 0111 -> 39
*/
#include <stdio.h>
int main() {
printf("40 ^ 15 = %d\n", 40 ^ 15);
return 0;
}
(4)取反运算(~)
按位取反运算:补码取反,再将取反后的补码转为原码;
补充:无符号的数据,取反后最高位为1,也不需要逆运算。
/**
* 按位取反运算:补码取反,再将取反后的补码转为原码。
* 1、正数取反:由于正数的原码和补码是相同的,取反的方式简便了些。
* 补码(原码) -> 取反 -> 补码逆运算 -> 反码逆运算(符号位不变) -> 取反后的原码
* 2、负数取反:
* 原码 -> 反码 -> 补码 -> 取反 -> 取反后的补码即原码
* 示例:
* 原码(补码) 取反的补码 补码逆运算-1 反码逆运算
* ~40 = 0010 1000 -> 1101 0111 -> 1101 0110 -> 1010 1001 = -41
*
* 原码(补码) 取反的补码 补码逆运算-1 反码逆运算
* ~15 = 0000 1111 -> 1111 0000 -> 1110 1111 -> 1001 0000 = -16
*
* 原码 反码 补码 取反
* ~-15 = 1000 1111 -> 1111 0000 -> 1111 0001 -> 0000 1110 = 14
*/
#include <stdio.h>
int main() {
printf("~40 = %d\n", ~40);
printf("~15 = %d\n", ~15);
printf("~-15 = %d\n", ~(-15));
return 0;
}
(5)左移运算符(<<)
规则:将数字的二进制补码整体左移,左边超出部分丢弃,右边空位补0
注意事项:
- 有符号数:左移后若最高位为
1,表示负数,结果是补码形式(有时称“逆运算”即补码还原) - 无符号数:左移后最高位为
1不用处理 - 特殊值 -128:左移后最高位为
1也不用处理
代码示例:
#include <stdio.h>
int main() {
/**
* 示例:
* 40 << 4 = 0010 1000 << 4 = 1000 0000 = -128 (特殊的不需要逆运算)
* 41 << 4 = 0010 1001 << 4 = 1001 0000 = 1000 1111 = 1111 0000 = -112
*/
int8_t p = 40;
int8_t X = 41;
p <<= 4; // p = p << 4;
X <<= 4; // p = p << 4;
printf("40 << 4 = %d\n", p);
printf("41 << 4 = %d\n", X);
return 0;
}
(6)右移运算符(>>)
规则:将数字的二进制补码整体右移,右边超出部分丢弃,左边空位补符号位(原最高位)
注意事项:
- 正数:左边空位补0
- 负数:左边空位补1
- 负数右移结果属于实现定义,不同编译器可能不同
- 移动位数不能为负或超过类型长度
代码示例:
#include <stdio.h>
int main() {
/*
23:
0001 0111【原码】
0001 0111【反码】
0001 0111【补码】 >> 2
-----------------
0000 0101【补码】 ---> 5
*/
printf(" 23 >> 2 = %d \n", 23 >> 2) ;
/*
-23:
1001 0111【原码】
1110 1000【反码】
1110 1001【补码】 >> 2
-----------------------------------------------
1111 1010【补码】 -> 1111 1001【反码】-> 1000 0110 【原码】 ==> -6
*/
printf(" -23 >> 2 = %d \n", -23 >> 2) ;
return 0;
}
(7)总结
综合代码示例:
#include <stdio.h>
#include <stdint.h>
int main() {
uint8_t a = 3; // 0000 0011
uint8_t b = 10; // 0000 1010
// 打印显示2个字符,个数不够,左边补0
printf("%02x\n", a & b); // 0000 0010,16进制为02
printf("%02x\n", a | b); // 0000 1011,16进制为0b
printf("%02x\n", a ^ b); // 0000 1001,16进制为09
uint8_t c = 10; // 0000 1010
uint8_t temp = ~c; // 1111 0101
printf("%02x\n", temp); // 1111 0101,16进制为f5
printf("%02x\n", c << 1); // 0001 0100,16进制为14
printf("%02x\n", c >> 1); // 0000 0101,16进制为05
return 0;
}
三、位运算——寄存器操作
1、第N位置1: a |= (1 << N)
拆解:(1 << N)
(1)把数字1左移N位
(2)得到的结果为只有第N位是1,其余为0的数;
例如:N=3 得到的结果为: 1 << 3 -> 0000 1000
a | =
(1)表示按位或然后赋值(全零为零,其余为一)
(2)规则:只要某位有1,结果该位就是1
例如:
int a = 5; // 0101
a |= (1 << 3);
0000 0101
| 0000 1000
-------------------
0000 1101 -> 把第三位成功置1;
2、把第N位清0:a &= ~(1 << N)
拆解:(1 << N)
(1)把数字1左移N位
(2)得到的结果为只有第N位是1,其余为0的数;
~(1 << N)
(1)按位取反
(2)第N位变为0,其余变为1
例如:
1<<2 0000 0100
~(1<<2) 1111 1011
a &= ...
(1)表示按位与然后赋值(全一为一,其余为零)
(2)规则:只要某位有0,结果该位就是0;
例如:
int a = 7; // 0111
a &= ~(1 << 1);
1 << 1 0000 0010
~(1 << 1) 1111 1101
& 0000 0111
------------------
0000 0101 -> 把第一位成功清0;
四、运算符优先级
优先级表格图片

801

被折叠的 条评论
为什么被折叠?



