c语言操作符初阶总结
1.算数操作符
+ - * / %
-
除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数。
-
对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法。
-
% 操作符的两个操作数必须为整数。返回的是整除之后的余数。
2.位移操作符
<< 左移操作符
>> 右移操作符
注:移位操作符的操作数只能是整数。
2.1左移操作符
- 移位规则
- 左边抛弃、右边补0
2.2右移操作符
移位规则:
首先右移运算分两种:
- 逻辑移位 左边用0填充,右边丢弃
- 算术移位 左边用原该值的符号位填充,右边丢弃
警告⚠ : 对于移位运算符,不要移动负数位,这个是标准未定义的。
例如:
int num = 10;
num>>-1;//error
3.位操作符
- & – 按位与
- | – 按位或
- ^ – 按位异或 —相同为0;相异为1
注:他们的操作数必须是整数。
//按位与
int main()
{
int a = 3;
int b = -5;
int c = a & b;
//00000000000000000000000000000011 - 3的补码
//10000000000000000000000000000101
//11111111111111111111111111111010
//11111111111111111111111111111011 - -5的补码
//00000000000000000000000000000011 - 3的补码
//00000000000000000000000000000011 - 3的补码 两个里面只要有0 就为0;两个都为1就为1;
//
//%d 意味着打印一个有符号的整数
//
printf("c=%d\n", c);
return 0;
}
//按位或
int main()
{
int a = 3;
int b = -5;
int c = a | b;
//00000000000000000000000000000011 - 3的补码
//10000000000000000000000000000101
//11111111111111111111111111111010
//11111111111111111111111111111011 - -5的补码
//00000000000000000000000000000011 - 3的补码
//11111111111111111111111111111011 - 补码 两个里面一个为1就为1 ;两个为0就为0;
//11111111111111111111111111111010 减一为反码
//10000000000000000000000000000101 符号位不变其他位取反为原码
//-5
//%d 意味着打印一个有符号的整数
//
printf("c=%d\n", c);
return 0;
}
位操作符的使用
不能创建临时变量(第三个变量),实现两个数的交换。
3^3 = 0 -> a^a=0
011
011
000
0^5=5 -> 0^a = a
000
101
101
3^3^5 = 5
3^5^3 = 5
异或操作符支持交换律
011
101
110
011
101
//创建了第三个变量
int main()
{
int a = 3;
int b = 5;
printf("交换前:a=%d b=%d\n", a, b);
a = a ^ b;//a=3^5
b = a ^ b;//3^5^5 --> b=3
a = a ^ b;//3^5^3 --> a=5
printf("交换后:a=%d b=%d\n", a, b);
return 0;
}
//会有溢出问题
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;
}
int main()
{
int a = 3;
int b = 5;
int c = 0;//空瓶
printf("交换前:a=%d b=%d\n", a, b);
c = a;
a = b;
b = c;
printf("交换后:a=%d b=%d\n", a, b);
return 0;
}
4.关系操作符
int main()
{
if (3 == 5)
{
}
//err
if ("abc" == "abcdef")//这样写是在比较2个字符串的首字符的地址
{
}
//两个字符串比较相等应该使用strcmp
return 0;
}
5.逻辑运算符
- && 左边为假,右边就不计算了
- || 左边为真,右边就不计算了
#include <stdio.h>
int main()
{
int i = 0, a = 0, b = 2, c = 3, d = 4;
//i = a++ && ++b && d++;
i = a++ || ++b || d++;
printf("a = %d\nb = %d\nc = %d\nd = %d\n", a, b, c, d);
return 0;
}
6.条件操作符(三目操作符)
exp1 ? exp2 : exp3;
//如果表达式1为真,则计算表达式2的结果
//如果表达式1为假,则计算表达式3的结果
//eg:
int main()
{
int a = 3;
int b = 0;
int max = (a > b ? a : b);
if (a > 5)
b = 3;
else
b = -3;
(a > 5) ? (b = 3) : (b = -3);//以上代码使用条件运算符写方法1
b = (a > 5 ? 3 : -3);//方法2
return 0;
}
7.逗号表达式
exp1, exp2, exp3, …expN
- 逗号表达式,就是用逗号隔开的多个表达式。 逗号表达式,从左向右依次执行。
- 整个表达式的结果是最后一个表达式的结果。
//代码1
int a = 1;
int b = 2;
int c = (a>b, a=b+10, a, b=a+1);//逗号表达式
c是多少?
//代码2
if (a =b + 1, c=a / 2, d > 0)
//代码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)
{
//业务处理
}
8.下标引用,函数调用和结构体成员
8.1[ ] 下标引用操作符
操作数:一个数组名 + 一个索引值
int main()
{
int arr[10] = { 0 };
//
//arr[7] --> *(arr+7) --> *(7+arr) --> 7[arr]
//
//arr是数组首元素的地址
//arr+7就是跳过7个元素,指向了第8个元素
//*(arr+7) 就是第8个元素
//
arr[7] = 8;
7[arr] = 9;
//[] arr 7
//3 + 5;
//5 + 3;
return 0;
}
8.2( ) 函数调用操作符
接受一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数。
//函数定义
int Add(int x, int y)
{
return x + y;
}
int main()
{
int a = 10;
int b = 20;
//函数调用
int c = Add(a, b);//() 就是函数调用操作符,操作数:Add,a,b
//
//sizeof a;
return 0;
}
8.3访问一个结构的成员
#include <string.h>
struct Stu
{
char name[20];
int age;
double score;
};
void set_stu(struct Stu* ps)
{
//strcpy((*ps).name, "zhangsan");
//(*ps).age = 20;
//(*ps).score = 100.0;
//(*ps).age 等价于 ps->age
strcpy(ps->name, "zhangsan");//结构体指针->成员
ps->age = 20;
ps->score = 100.0;
}
//void print_stu(struct Stu ss)
//{
// printf("%s %d %lf\n", ss.name, ss.age, ss.score);//结构体对象.成员
//}
void print_stu(struct Stu* ps)
{
printf("%s %d %lf\n", ps->name, ps->age, ps->score);
}
int main()
{
struct Stu s = {0};
set_stu(&s);//数组传的是地址
print_stu(&s);
return 0;
}
9.隐式类型转换
- C的整型算术运算总是至少以缺省(缺省=默认)整型类型的精度来进行的。
- 为了获得这个精度,表达式中的字符和短整型操作数在使用之前被转换为普通整型,这种转换称为整型提升。
为什么需要整形提升?
C的整形算术运算总是至少以缺省类型的精度来进行的,为了获得这个精度,表达式中的字符型和短整型操作数在使用之前被转换 为普通类型,这种转换称为整形提升. 比如: char a,b,c; a = b + c; b和c的值被提升为普通整形,然后在执行加法运算.
int main()
{
char a = 5;
//00000000000000000000000000000101
//00000101 - a(char类型1个字节8个比特位)
char b = 126;
//00000000000000000000000001111110
//01111110 - b(char类型1个字节8个比特位)
char c = a + b;
//00000000000000000000000000000101 - a
//00000000000000000000000001111110 - b
//00000000000000000000000010000011
//10000011 - c(char类型1个字节8个比特位)
//11111111111111111111111110000011 - 补码(整型提升后)
//11111111111111111111111110000010 - 反码
//10000000000000000000000001111101 - 原码
//
printf("%d\n", c);//-125
return 0;
}
1.无符号整形提升,高位补0
2.有符号的整形提升,高位补其符号位
- 负数的整形提升
char a = -1;
a为负数,其补码为1111 1111,占8个比特位
(vs 2013 默认为有符号的)char为有符号的char
整形提升时高位补充符号位 1
提升结果为:1111 1111 1111 1111 1111 1111 1111 1111 - 正数的整形提升
char b = 1;
b为正数,其补码为0000 0001,占8个比特位
char为有符号char
整形提升高位补充符号位 0
提升结果为:0000 0000 0000 0000 0000 0000 0000 0001