知识点1:算数操作符:+ - * / %
1、/—对于除,若两个数都为整数,执行整数除法;只要有浮点数才执行浮点数除法
2、%—对于取余,两个数必须为整数,返回的是整除之后的余数;取模操作符绝对
不能浮点数类型
3、注意:浮点数类型用float 或 double —打印时使用 %lf—打印小数点后六位
int main()
{
// /除操作符
int a = 1;
int b = 3;
printf("%d \n", a / b);
int c = 7 / 2;
printf("%d \n", c);
double d = 7.0 / 2;
printf("%lf \n", d);
float d1 = 7.0 / 2;
printf("%f \n", d1);
// %模操作符
int e = 4 % 3;
printf("%d \n", e);
return 0;
}
知识点2:移位操作符:>>(右移) <<(左移)
1、移动的是二进制位
2、整数的二进制表现形式---原码、反码、补码
正整数:原码、反码、补码相同
负整数:直接写的二进制序列 ---原码
原码字符位不变,其他位按位取反 ---反码
反码+1 ---补码
3、内存中存储整数时存储的是补码---计算时转换为补码
4、算数右移:左边补符号位,右边丢弃----某些情况下,右移除二的效果
逻辑右移:左边补0,右边丢弃
算数右移,逻辑右移---跟编译器有关
5、左移:左边丢弃,右边补0----某些情况下,左移乘二的效果
6、移位时绝对不能移位的数字为负数---int num = 10;num >> -1;
7、操作数必须为整数
int main()
{
//正整数右移
//分析:整数4个字节 -- 32位
// 原码、反码、补码:00000000 00000000 00000000 00001110----第一位0代表符号位-正数
// 右移一位:0 00000000 00000000 00000000 0000111 ---补符号位0---VS算数右移 ---7
int a = 14;
int b = a >> 1;
printf("%d ", b);//7
//负整数右移
//分析:原码:1000000 0000000 00000000 00000001 --- 第一位1代表符号位-负数
// 反码:1111111 1111111 11111111 11111110
// 补码:1111111 1111111 11111111 11111111
// 右移一位:1 1111111 1111111 11111111 1111111 ---补符号位1 --- -1
int a1 = -1;
int b1 = a1 >> 1;
printf("%d ", b1);//-1
//正整数左移
//分析:整数4个字节 -- 32位
// 原码、反码、补码:00000000 00000000 00000000 00001110----第一位0代表符号位-正数
// 左移一位:0000000 00000000 00000000 00001110 0 ---补0 ---4+8+16 = 28
int a2 = 14;
int b2 = a2 << 1;
printf("%d ", b2);//28
//负整数左移
//分析:原码:1000000 0000000 00000000 00000001 --- 第一位1代表符号位-负数
// 反码:1111111 1111111 11111111 11111110
// 补码:1111111 1111111 11111111 11111111
// 左移一位:111111 1111111 11111111 11111111 0 ---补0
// - 1
// 反码:111111 1111111 11111111 11111110 1
// 原码:100000 0000000 00000000 00000001 0 --- -2
int a3 = -1;
int b3 = a3 << 1;
printf("%d ", b3);//-2
return 0;
}
知识点3:位操作符:& | ^
1、&:同时为1 —为1
2、|:同时为0 —为0
3、^:相同为0,不同为1
4、按二进制位进行&,|,^
//知识点3:位操作符:& | ^
// 1、&:同时为1 ---为1
// 2、|:同时为0 ---为0
// 3、^:相同为0,不同为1
// 4、按二进制位进行&,|,^
int main()
{
//& 按位与
//3:00000000 00000000 00000000 00000011
//5:00000000 00000000 00000000 00000101
// 00000000 00000000 00000000 00000001 ---1
int a = 3;
int b = 5;
int c = a&b;
printf("%d\n", c);
//| 按位或
//3:00000000 00000000 00000000 00000011
//5:00000000 00000000 00000000 00000101
// 00000000 00000000 00000000 00000111 ---7
int a1 = 3;
int b1 = 5;
int c1 = a1|b1;
printf("%d\n", c1);
//^ 按位异或
//3:00000000 00000000 00000000 00000011
//5:00000000 00000000 00000000 00000101
// 00000000 00000000 00000000 00000110 ---6
int a2 = 3;
int b2 = 5;
int c2 = a2^b2;
printf("%d\n", c2);
return 0;
}
案列1:不能创建临时变量(第三个变量),实现两个数的交换
//创建变量
int main()
{
int a = 3;
int b = 5;
int temp = 0;
printf("a = %d b=%d\n", a, b);
temp = a;
a = b;
b = temp;
printf("a = %d b=%d\n", a, b);
return 0;
}
//不创建变量
//方法1:存在溢出
int main()
{
int a = 3;
int b = 5;
printf("a = %d b=%d\n", a, b);
a = a + b;//和给a
b = a - b;//和减b为a--给b ---b=a
a = a - b;//和减b(实际交换了为a),和减a为b--给a ---a=b
printf("a = %d b=%d\n", a, b);
return 0;
}
//方法2:异或
int main()
{
int a = 3;
int b = 5;
printf("a = %d b=%d\n", a, b);
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("a = %d b=%d\n", a, b);
return 0;
}
案列2:求一个整数存储在内存中的二进制中1的个数 思想:若a按位与1为1—则该位为1;再将a向右移动1位,依次完成32位比特位
int BinaryReturn(int x)
{
int i = 0;
int count = 0;
for (i = 0; i < 32; i++)
{
if (((x >> i) & 1) == 1)
count++;
}
return count;
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = BinaryReturn(n);
printf("%d\n", ret);
return 0;
}
知识点4:赋值操作符–复合赋值操作符
1、赋值操作符 --- = 2、复合赋值操作符 --- +=,-=,*=,/=,%=,&=,|=,^=,>>=,<<=
int main()
{
int a = 10;
a = 20;
int num = 0;
num = num + 1;
num += 1;
int num = 0;
num = num >> 1;
num >>= 1;
return 0;
}
知识点5:单目操作符—有一个操作数
! - 逻辑反操作 - - 负值 + - 正值 & - 取地址 * - 间接访问操作符(解引用操作符) sizeof - 操作数的类型长度、 ~ - 对一个数二进制按位取反 -- - 前置、后置-- ++ - 前置、后置++ (类型) - 强制类型
//操作符 ! - 逻辑反操作
int main()
{
int a = 3;
printf("%d\n", !a);//0为假,非0为真
int flag = 0;
if (flag)
{
//如果flag为真进来
}
if (!flag)
{
//如果flag为假进来
}
return 0;
}
//操作符+ -
int main()
{
int a = -1;
a = -a;
a = +a;
printf("%d\n", a);
return 0;
}
//操作符& *
int main()
{
int a = 10;
int* pa = &a;//将a的地址存在pa中---pa是一个指针变量---类型为int*
printf("%p\n", pa);//等价于printf("%p\n", &a)
*pa = 20;//通过pa找到a的值
printf("%d\n", a);
return 0;
}
//操作符sizeof---计算变量所占空间的大小
int main()
{
int a = 10;
//计算变量所占空间的大小
printf("%d\n", sizeof(a));//4
printf("%d\n", sizeof(int));//4--类型不能省略括号
printf("%d\n", sizeof a);//4
//计算数组的总大小,单位为字节
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
printf("%d\n", sizeof(arr));//10*sizeof(int)=40
printf("%d\n", sizeof (int [10]));//数组类型--40
//类型为:除过变量名就是类型
return 0;
}
// case1:陷阱1
int main()
{
int a = 5;
short s = 3;
printf("%d\n", sizeof(s = a + 3));//2--与s的类型short类型字节有关
printf("%d\n", s);//3 不改变s的值
return 0;
}
//case2:陷阱2---指针大小不会随类型变换而变换,32位-4字节;64位-8字节
void test1(int arr[])
{
printf("%d\n", sizeof(arr));//(2)--4或者8
}
void test2(char ch[])
{
printf("%d\n", sizeof(ch));//(4)--4或者8
}
int main()
{
int arr[10] = { 0 };
char ch[10] = { 0 };
printf("%d\n", sizeof(arr));//(1)--40
printf("%d\n", sizeof(ch));//(3)--10
test1(arr);
test2(ch);
return 0;
}
//操作符~
int main()
{
int a = 0;
printf("%d\n", ~a);
//分析:00000000 00000000 00000000 00000000 -补码
// 11111111 11111111 11111111 11111111 -补码
// 11111111 11111111 11111111 11111110 -反码
// 10000000 00000000 00000000 00000001 -原码 -- -1
return 0;
}
//案列:变某一位为1,并将其还原
int main()
{
int a = 10;
//二进制为:00000000 0000000 0000000 00001010 --- 将第五位变为1
// 00000000 0000000 0000000 00010000 --- 1 << 4
// 或|
// 00000000 0000000 0000000 00011010 --- 或 ---将第五位变为1
// 11111111 1111111 1111111 11101111 --- ~(1<<4)
// 与&
// 00000000 0000000 0000000 00001010 --- 与 ---将第五位变为1
a = a | (1 << 4);
printf("%d\n", a);//26
a = a & (~(1 << 4));
printf("%d\n", a);//10
return 0;
}
//操作符++ --
int main()
{
int a = 10;
int b = ++a;//先++ 后使用
printf("b = %d a=%d\n", b, a);//b=11,a=11
int c = a++;//先使用,后++
printf("c = %d a=%d\n", c, a);//c=11,a=12
int d = a--;//先使用,后--
printf("d = %d a=%d\n", d, a);//d=12,a=11
int e = --a;//先--后使用
printf("e = %d a=%d\n", e, a);//e=10,a=10
return 0;
}
//操作符 (类型)
int main()
{
int a = (int)3.14;//转换为整形
printf("%d\n", a);
return 0;
}
知识点6:关系操作符
>,<,>=,<=,!=,== == - 等于 = - 赋值
int main()
{
int a = 10;
if (10 == a)
{
printf("%d \n", a);
}
}
知识点7:逻辑操作符
&& -两个均为真 则为真
|| -两个均为假 则为假
注意:&&从左到右操作时,第一个为假,则不用计算后面
||从左到右操作时,第一个为真,则不用计算后面
int main()
{
int a = 10;
int b = 0;
int c = a&&b;
printf("%d\n", c);//0
int d = a||b;
printf("%d\n", d);//1
return 0;
}
//case:&&与||陷阱
int main()
{
int i = 0, a = 0, b = 2, c = 3, d = 4;
//i = a++ && ++b && d++; //a++时,i=0,a =1 ---则为假,不用计算后面 - a =1,b = 2, c = 3, d = 4
i = a++||++b||d++;//i=0,a=1;b=3,i=3 --为真,不用计算后面,a=1;b=3,c = 3, d = 4
printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
return 0;
}
int main()
{
int i = 0, a = 1, b = 2, c = 3, d = 4;
//i = a++ && ++b && d++; //i=1,a=2;b=3,i=3;i=4,d=5 --- a=2,b=3,c = 3, d = 4
i = a++ || ++b || d++;//i=1,a=2 ---为真,不用计算后面,a=2,b = 2, c = 3, d = 4
printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);
return 0;
}
知识点8:条件操作符 — 三目操作符 - exp1?exp2:exp3
int main()
{
int a = 10;
int b = 20;
int max = 0;
if (a > b)
{
max = a;
}
else
{
max = b;
}
printf("max = %d\n", max);
a > b ? a : b;
printf("max = %d\n", max);
return 0;
}
知识点9:逗号表达式 - exp1,exp2,exp3,…,expN
从左向右依次执行。整个表达式的结果是最后一个表达式的结果。与前面的结果没关系,前面结果只是为了计算。
int main()
{
//代码1
int a = 1;
int b = 2;
int c = (a>b, a = b + 10, a, b = a + 1); //整个表达式的结果是最后一个表达式的结果。
//printf("%d %d %d\n", a, b, c);//12,13,13
//代码2
int d = 2;
if (a = b + 1, c = a / 2, d > 0)//只决定最后一个表达式
{
printf("%d %d %d %d\n", a, b, c,d);//14,13,7,2
}
else
{
printf("输入错误");
}
//代码3 a = get_val();
count_val(a);
while (a > 0)
{
//业务处理
a = get_val();
count_val(a);
}
//用逗号表达式修改之后
while (a = get_val(), count_val(a), a>0)
{
//业务处理
}
}
知识点10:下标引用、函数调用和结构成员
[] -下标引用操作符 - 一个数组名 + 一个索引值 () -函数调用操作符 - 接受一个或者多个操作数:第一个操作数是函数名, 剩余的操作数就是传递给函数的参数。 . -> -结构成员
// [] -下标引用操作符
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
printf("%d\n", arr[4]);// [] - 下标引用操作符 -- 两个操作数 - 一个为arr数组名,一个4参数
return 0;
}
//() -函数调用操作符
int Add(int x, int y)
{
return x + y;
}
int main()
{
int a = 10;
int b = 20;
int sum = Add(a, b);
printf("sum = %d\n", sum);//() -函数调用操作符 ---三个操作数 - 一个为Add函数名,另外两个为a,b参数
return 0;
}
// . -> -结构成员
#include <stdio.h>
#include <string.h>
struct Stu //Stu结构体类型
{
char name[10];
int age;
char sex[5];
double score;
};
int main()
{
struct Stu s = { "张三", 20, "男" , 98.89 };//s为结构体变量
//s.name = "张三";//对于字符串不能直接赋值 -- 使用strcpy
//strcpy(s.name, "张三");
printf("%s\n", s.name);
printf("%d\n", s.age);
printf("%s\n", s.sex);
printf("%lf\n", s.score);
printf("-----------------\n");
struct Stu* ps = &s;//将s的地址存在ps中,struct Stu*为结构体地址类型
printf("%s\n", ps->name);
printf("%d\n", ps->age);
printf("%s\n", ps->sex);
printf("%lf\n", ps->score);
return 0;
}
#include <stdio.h>
#include <string.h>
struct Stu //Stu结构体类型
{
char name[10];
int age;
char sex[5];
double score;
};
void set_age1(struct Stu stu) {
stu.age = 18;
}
void set_age2(struct Stu* pStu) {
pStu->age = 18;//结构成员访问
}
int main()
{
struct Stu stu;
struct Stu* pStu = &stu;//结构成员访问
stu.age = 20;//结构成员访问
set_age1(stu);
pStu->age = 20;//结构成员访问
set_age2(pStu);
return 0;
}