c语言入门学习笔记--操作符详解(五)
本系列博文仅为博主个人学习笔记,通过博客理清学习思路用于复习。如有记述不周到的地方请谅解;如能指出,万分感谢。
操作符
1.各种操作符介绍
1.1算术操作符
+ - * / %
1.以上除啦 % 操作符之外,其他的几个操作符都可以作用于整数和浮点数。
2. / 操作符如果两个操作符都是整数,执行的是整数除法。而只要有一个操作数是浮点数,另一个操作数就会提高精度提升为浮点数,进行浮点数除法。
3. % 操作符的两个操作数必须为整形,返回的是整除之后的余数。
1.2移位操作符
<< >>
左 移 操 作 符 \pmb{左移操作符} 左移操作符左移操作符左移操作符 移位规则:
左边抛弃,右边补零
右 移 操 作 符 \pmb{右移操作符} 右移操作符右移操作符右移操作符 移位规则:
右移运算分为两种:
1. 算术右移 左边用原该值的符号位填充,右边抛弃
2. 逻辑右移 左边用0填充,右边抛弃
注意:左移右移并不会改变原来变量的值。
int i = 2 ;
i << 2;
printf("%d",i); //i 还是2
1.3位操作符
& //按位与 只要其中一个为零,则结果为零
| //按位或 只要其中一个为1,则结果为1
^ //按位异或 两个数的每个二进制位相同为1,不相同为0
注: 位操作符的两个操作数必须为整数
练习:
不能创建临时变量(第三个变量),实现两个数的交换。
第一种方法:
int main(){
int a = 10 ;
int b = 20 ;
a = a + b ;
b = a - b ;
a = a - b ;
}
这种方法满足啦题目的要求,但是仍然有些缺陷。我们都知道整形都有自己值得范围,如果两个交换数本身就非常大,它们加起来超过啦它们值的范围,就会造成溢出的现象,程序的结果就会与预期的不大相同,故就有啦第二种方法。
#include <stdio.h>
int main(){
int a = 10 ;
int b = 20 ;
a = a ^ b ;
b = a ^ b ; //这里相当于 b = a ^ (b ^ b) ; 异或有结合律 ,
a = a ^ b ; // 这里相当于 a = a ^ b ^ a ;
}
分析 : 根据异或操作符运算规则,可以得出两个结论
1 .任何数 ^ 0 = 任何数
2. 任何数 ^ 任何数 = 0
相比之下,这种方法就不会有第一种方法的顾虑啦。
练习 : 编写代码实现:求一个整数存储在内存中的二进制中1的个数
方法一:采用数学的方法:余数短除法
int main() {
int num = 10;
int count = 0 ;
while(num){
if(num % 2 == 1){
count++;
}
num = num / 2 ;
}
printf("二进制中1的个数%d",count);
}
方法二:用位运算法和移位运算法的方法
//
int main(){
int num = 10 ;
int i = 0 ;
int count = 0 ;
for(i = 0 ; i < 32 ; i++){
if((num >> i) & 1){
count++;
}
}
printf("二进制中1的个数%d",count);
}
1.4赋值操作符
复合赋值符
+=
-=
*=
/=
% =
>>=
<<=
&=
|=
^=
**这些操作符都可以写成复合的效果**。比如:
int x = 10 ;
x = x + 10 ;
x += 10 ; / / 复合赋值
其他运算符一样的道理,这样写更加的简洁。
1.5单目操作符
! 逻辑反操作
- 负值
+ 正值
& 取地址
sizeof 求操作数的类型长度
~ 对一个数的二进制位按位取反
- - 前置 、后置- -
++ 前置、后置 ++
* 间接访问操作符(解引用操作符)
(类型) 强制类型转换
代码演示:
int main() {
int a = -10;
int* p = NULL;
a = -a;
p = &a;
printf("%d\n", sizeof(a));
printf("%d\n", sizeof(int));
printf("%d\n", sizeof a);
//printf("%d\n", sizeof int);error
return 0;
}
运行结果 :
1.6逻辑操作符
&& 逻辑与
|| 逻辑或
注意:区别于位操作符,逻辑与与按位与,逻辑或与按位或
1 & 2--------> 0
1 && 2 -------> 1
1 | 2 -------->3
1 || 2 -------->1
逻辑与逻辑或的特点:
#include <stdio.h>
int main() {
int i = 0, a = 0, b = 2, c = 3, d = 4;
i = a++ && ++b && d++;
printf("i = %d ,a = %d,b = %d ,c = %d\n", i, a, b, c, d);
return 0;
}
请大家先动动脑筋想想,再往下看运算结果,跟你想的是否一致?
exp 1&& exp 2 逻辑与操作符,有这么一个特点 ,若exp1 的表达式值为0 ,则exp2无需继续运算,当程序中 执行到i = a++时,表达式值为0,则exp2,exp3,不需要继续执行,故 i 被赋值为0 。同样的道理 exp1 | | exp2 也有这样的特点,这要exp1 的表达式值为真,则后面的表达式无需计算。
1.7关系操作符
>
>=
<
<=
!= 用于测试”不等于“
== 用于测试“相等” 注意:字符串不能用“==”来比较
关系操作符主要就是比较大小,比较容易,但有一个新手易错的地方就是,容易把== 漏写成啦 = ,两个意思完全就不一样啦,一个是关系操作符,一个是赋值操作符。
1.8条件操作符
exp2 ? exp2 : exp3
如何将下面的语句用条件操作符表示
if(a >1){
b = 3 ;
}
else{
b = -3 ;
}
//答
a > 1 ? b = 3 : b = -3
1.9逗号操作符
exp1 ,exp2 ,exp3 …expn
逗号表达式,就是用逗号隔开的多个表达式。逗号表示式,从左到右执行,整个表达式的结果是最后一个表达式。
//代码
a = getval();
count_val(a);
while(a > 0 ){
//业务处理
a = getval();
count_val(a);
}
//用逗号表达式改写上面代码可以起到同样的效果
while (a = getval(),count_val(a), a > 0 );
1.10下标引用、函数调用和结构体成员
1 、[ ] 下标引用操作符
操作数 : 一个数组名 + 一个索引值
int array[10] ; // 创建数组
array[9] = 10 ; // [] 的两个操作数为 array , 9
2、 () 函数调用操作符 接收一个或者多个操作数 : 第一个操作数是函数名,剩余的操作数是传递给函数的参数。
#include <stdio.h>
test1(){
printf("hehe");
}
test2(const char* str){
printf("%s",str);
}
int main(){
test1();
test2("hello,world");
return 0 ;
}
3 、访问一个结构的成员
. 结构体.成员名
-> 结构体指针->成员名
#include <stdio.h>
struct Stu {
int age;
char name[20];
};
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);
printf("%d", pstu->age);
return 0;
}
}
以上就是本章内容,谢谢观看!!!
下一章将继续讲解表达式如何用这些操作符进行运算的呢?要讲究什么规则呢? 欢迎大家关注,下期再见。