#include<stdio.h>
int main()
{
int a = 5;
int b = 2;
int c = 0;
printf("a+b = %d\n", a + b);//相加
printf("a-b = %d\n", a - b);//相减
printf("ab = %d\n", a * b);//相乘
printf("a/b = %d\n", a / b);//求商
printf("a%%b = %d\n", a % b);//取模
return 0;
}
#include <stdio.h>
int main()
{
/double a = 5.0 / 2;/
double a = 5 % 2.0;//报错
printf("a = %lf", a);
return 0;
}
#include<stdio.h>
int main()
{
int a = 3; //00000000 00000000 00000000 00000011
int b = 5; //00000000 00000000 00000000 00000101
int c1 = a & b; //00000000 00000000 00000000 00000001 =1
int c2 = a | b; //00000000 00000000 00000000 00000111 =7
int c3 = a ^ b; //00000000 00000000 00000000 00000110 =6
printf("c1 = %d\n", c1);
printf("c2 = %d\n", c2);
printf("c3 = %d\n", c3);
return 0;
}
练习1:不用临时变量,交换a,b的值
不用临时变量,交换a,b的值
假设我们给定两个数,a = 3, b = 5;
要实现两个数的交换,我们会想到醋和酱油交换的生活案例,我们会先找一个空瓶子,先将醋或者酱油倒到空瓶子中,(假设将醋先倒入空瓶子中)然后我们会将酱油倒入原醋瓶中,将原空瓶中的醋倒入酱油瓶中。
方法①根据这种方式,我们会先创建一个临时变量来用于两者的数值交换
#include <stdio.h>
int main()
{
int a = 3;
int b = 5;
int temp = 0;
printf("before:a = %d,b = %d\n", a, b);
temp = a;
a = b;
b = temp;
printf("after:a = %d,b = %d", a, b);
return 0;
}
但是我们题目中明确要求不能创建变量,所以这种方式明显不合适。
这时候我们考虑另外一种方式,②从数学的角度出发:如果我先将 a与b之和放到a到当中 然后再用两者之和减去b不就得到a了吗,并把这个值赋给b,实现了a的值转移给b 。同理,用两者之和减去刚刚赋予a值到b中的b,就能得到原b的值(听起来有点绕是不,简单来说:就是 值:a + b - a = b = > 变量a
//方法一:加减法include<stdio.h>
//不创建临时变量实现两个数的交换
int main()
{
int a = 3;
int b = 5;
printf("before:a = %d,b = %d\n", a, b);
a = a + b;
b = a - b;//将a的值给b
a = a - b;//将b的值给a
printf("after:a = %d,b = %d", a, b);
return 0;
}
//异或办法include<stdio.h>
//不创建临时变量实现两个数的交换
int main()
{
int a = 3;
int b = 5;
printf("before:a = %d,b = %d\n", a, b);
a = a ^ b;
b = a ^ b;
a = a ^ b;
printf("after:a = %d,b = %d", a, b);
return 0;
}
#include<stdio.h>
int main()
{
int a = 0;
int count = 0;
scanf("%d", &a);
while (a)
{
if ((a % 2) == 1)
count++;
a = a / 2;
}
printf("count = %d\n", count);
return 0;
}
这种方式看似正确,但是当我们输入负数的时候,比如 - 1, - 1补码为11111111 11111111 11111111 11111111 正确答案应该为:32 ,而我们程序运行却得到0。
(实际上这种方式还有补救方法,只要将 负数看作无符号位的整型,将a定义从 int a = 0; 成更改成unsigned int a - 1就会被当作一个超级大的数字11111111 11111111 11111111 11111111 来处理)
#include<stdio.h>
int main()
{
int a = 0;
int count = 0;
int i = 0;
scanf("%d", &a);
for (i = 0; i < 32; i++)
{
if (1 == ((a >> i) & 1))
{
count++;
}
}
printf("count = %d\n", count);
return 0;
#include<stdio.h>
int main()
{
int a = 0;
int count = 0;
int i = 0;
scanf("%d", &a);
while (a)
{
count++;
a &= a - 1;
//a = a & (a - 1);
}
printf("count = %d\n", count);
return 0;
int weight = 80;//单位kg
weight = 60;//对80不满意,重新赋值成60
double salary = 10000.0;
salary = 30000.0;//对salary只有10000.0不满意,变成30000.0
//赋值操作符也可以连续使用,比如
int a = 10;
int x = 0;
int y = 20;
a = x = y + 1; //连续赋值 //赋值操作符是从右往左计算的
//等同于:
x = y + 1;
a = x;
一般我们都是用分开的形式,不用连续赋值的形式,因为分开表示的方法更加容易阅读和理解,且易于调试。 ②复杂赋值操作符
+= 、-= 、 = 、 /=、 %= 、 >>=、 <<=、 &=、 |=、 ^=
举例:
int x = 10;
x = x + 10;
等同于:x += 10;
#include<stdio.h>
int main()
{
int a = 1;
printf("%d\n", a += 1);
printf("%d\n", a -= 1);
printf("%d\n", a = 2);
printf("%d\n", a /= 2);
printf("%d\n", a %= 2);
printf("%d\n", a <<= 1);
printf("%d\n", a >>= 1);
printf("%d\n", a &= -1);
printf("%d\n", a |= 1);
printf("%d\n", a ^= 1);
return 0;
}
#include<stdio.h>
int main()
{
int a = 10;
int b = 20;
int max;
//if (a > 5)
// b = 3;
//else
// b = -3;
//b = a > 5 ? 3 : -3;
max = a > b ? a : b;
printf("a = %d\nb = %d\nmax = %d\n", a, b, max);
return 0;
}
#include<stdio.h>
int main()
{
int a = 1;
int b = 2;
int c = (a > b, a = b + 10, a, b = a + 1);
printf("%d\n", c);
return 0;
}
讲解:这里我们要输出c的值,那么c的值是什么呢?
int c = (a > b, a = b + 10, a, b = a + 1);
这里初始化c的时候应用了逗号表达式,逗号表达式从左向右依次执行,整个表达式结果为最后一个表达式的结果,我们按照这个原则去推导,a > b 执行但是没有结果 a = b + 10 相当于a = 2 + 10 = 12, a执行但不产生结果,b = a + 1 = 12 + 1 = 13,整个表达式的值也等于b 即c = 13。
对于这个结果我们可以运行程序验证一下。
拓展:那这里a, b的值分别为多少呢?
a = 12, b = 13 不再是原本的1和2,说明int c = (a > b, a = b + 10, a, b = a + 1); 中运算的结果有效接保留了下来。 10.下标引用、函数调用和结构成员 1.下标引用操作符 [ ]
操作数: 一个数组名 + 一个索引值
#include<stdio.h>
//2.这个地方的()不是函数调用操作符,是函数定义的语法规则
int get_max(int x, int y)
{
return x > y ? x : y;
}
int main()
{
int a = 10;
int b = 20;
//1.调用函数的时候使用的() 就是函数调用操作符
int max = get_max(a, b);
//3.这里的函数调用操作符()的操作数为 函数名get_max,函数参数a,函数参数b 总共三个操作数
//4.对于函数调用操作符()而言,其操作数至少要有一个(函数名),可以有多个
printf("max = %d\n", max);
return 0;
}
3.访问一个结构的成员 . ->
思考:如何创建结构体类型和结构体类型变量呢?
#include<stdio.h>
//1.现实中为了描述复杂的对象,构建结构体类型
//2.比如学生,有姓名,年龄,学号等信息
//创建一个结构体类型
struct Stu //3.struct Stu是一个结构体类型,表示学生类型
//类型是用来创建变量的
{char name[20];//姓名
int age;//年龄
char id[20];//学号
};
int main()
{int a = 10;
//使用struct Stu这个类型创建了一个学生对象s1,并初始化
struct Stu s1 = { "张三",20,"20210403" };
return 0;
}结构体类型和结构体类型变量详解:
②算术转换
如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数的转换为另一个操作数的类型,否则操作就无法进行。下面的层次体系称为寻常算术转换。
long doub1e
double
float
unsigned long int
long int
unsigned int
int
如果某个操作数的类型在上面这个列表中排名较低,那么首先要转换为另外一个操作数的类型后执行运算。(比如说int类型跟float类型参与运算,先要将int转换为float类型,然后float类型与float类型运算)
int a = 1;
float b = 2.0
b = a + b;
(会先将a转换为float类型 a = 1.00000)
警告 : 但是算术转换要合理,要不然会有一些潜在的问题。
例如:排名高的类型向低位转换的时候会出现精度丢失。
float f = 3.14;int num = f;//隐式转换,会有精度丢失
注释∶代码1在计算的时候,由于比 + 的优先级高,只能保证,的计算是比 + 早,但是优先级并不能决定第三个 比第一个 + 早执行。
所以表达式的计算机顺序就可能是︰
a bc d
a b + c de f
a b + c d + e f
或者 :
a bc de f
a b + c d
a b + c d + e f 表达式2