文章目录
C语言中操作符总共有10种,分别是:
算术操作符,移位操作符,位操作符,赋值操作符,单目操作符,关系操作符,逻辑操作符,条件操作符,逗号表达式,下标引用、函数调用和结构成员。
下面让我为大家一一介绍这些操作符
一、算数操作符
符号:+ - * / %
- 除了 % 操作符之外,其他的几个操作符可以作用于整数和浮点数。
- 对于 / 操作符如果两个操作数都为整数,执行整数除法。而只要有浮点数执行的就是浮点数除法。
示例:
int main()
{
int a = 5 / 2;
double b = 5 / 2;
printf("%d\n ",a);
printf("%lf\n",b);
return 0;
}
由图可以看出,如果操作数是整数,那么无论接受类型是什么,最后都只会执行整数除法(小数自动删除)。
但是如果我们将操作数中的一位或者两位改变结果就会不一样
int main()
{
int a = 5.0 / 2;
double b = 5.0 / 2;
printf("%d\n",a);
printf("%lf\n",b);
return 0;
}
在改变了操作数后,执行的就是浮点数除法,a依然无变化是因为它只能接受整形。
3. % (取模)操作符的两个操作数必须为整数,返回的是整除之后的余数。
示例:
int main()
{
int a = 5 % 2;
printf("%d\n",a);
return 0;
}
二、 移位操作符
注意:移动的是二进制位
符号:
<< 左移操作符
>> 右移操作符
注:移位操作符的操作数只能是整数。
0. 二进制(原、反、补码):
对于一个整数来说,一个整数有4个字节,32个比特位
它的二进制序列也就是32个比特位
对于有符号的整数来说,首位是符号位
符号位位0代表正数,为1代表负数
对于无符号的整数来说,没有符号位,所有位都是有效位
整数的二进制表示形式有三种:原码,反码,补码
原码:按照数值正负,直接写出的二进制序列
反码:原码的符号位不变,其它位按位取反
补码:在反码基础上二进制位+1
注意:数据在内存中存储是以补码形式,但打印是以原码形式
正整数而对原码、反码、补码相同
负整数的原、反、补码则需要按上面操作计算
例如:
int a = 7;
//原、反、补码:00000000000000000000000000000111
int b = -7;
//原码:10000000000000000000000000000111
//反码:11111111111111111111111111111000
//补码:11111111111111111111111111111001
1.左移操作符
移位规则(移动的是补码):
左边抛弃、右边补0
注意:移位对于原数字无影响,需要新找一个值来接受移位后的值
例1:
左移操作符
例2:
int b = -7;
int c = b << 1;
//原码:10000000000000000000000000000111 - b
//反码:11111111111111111111111111111000
//补码:11111111111111111111111111111001
//取反后:
//补码:11111111111111111111111111110010 - c
//反码:11111111111111111111111111110001
//原码:10000000000000000000000000001110
printf("%d\n",b);
printf("%d\n",c);
3.2 右移操作符
移位规则:
右移运算分两种(基本都是算数移位):
- 逻辑移位(编译器规定,但我没遇到过)
左边用0填充,右边丢弃- 算术移位(绝大部分编译器采用)
左边用原该值的符号位填充,右边丢弃
例:
警告⚠ :
对于移位运算符,不要移动负数位,这个是标准未定义的。
例如:int a = 10;
int b = a >> -1;
三、位操作符
操作符有:
& //按位与
| //按位或
^ //按位异或
注:他们的操作数必须是整数。
1.按位与 &
对应的补码中二进制位只要有0就为0,两个都为1才为1
a & 1 可以求a的二进制位的最后一位
例:
int a = 7;
int b = -14;
int c = a & b;
//a 的补码:00000000000000000000000000000111
//b 的补码:11111111111111111111111111110010
//a&b 补码:00000000000000000000000000000010
//a&b 首符号位为0,是正数,正数原、反、补码相同
2.按位或 |
对应的补码中二进制位只要有1就为1,两个都为0才为0
例:
int a = 7;
int b = -14;
int c = a | b;
//a 的补码:00000000000000000000000000000111
//b 的补码:11111111111111111111111111110010
//a|b 补码:11111111111111111111111111110010
//a|b 反码:11111111111111111111111111110011
//a|b 原码:10000000000000000000000000000100
3.按位异或 ^
对应的补码中二进制位相异位1,相同为0
a ^ a=0 ; a ^ 0 =0
例:
int a = 7;
int b = -14;
int c = a ^ b;
//a 的补码:00000000000000000000000000000111
//b 的补码:11111111111111111111111111110010
//a^b 补码:11111111111111111111111111110101
//a^b 反码:11111111111111111111111111110110
//a^b 原码:10000000000000000000000000001001
相应练习请移步:C语言小白急救 操作符相关练习1
四、赋值操作符
普通符号: =
复合赋值符
+=
-=
*=
/=
%=
>> =
<<=
&=
|=
^=
赋值操作符是一个很棒的操作符,他可以让你得到一个你之前不满意的值。也就是你可以给自己重新赋值。
1.普通赋值
普通赋值是使用: =
例如:int a = 0;
2.复合赋值
复合赋值符是其他运算符复合的效果:
例如:
int a = 0;
a = a + 2;//普通赋值
a += 2;//复合赋值
//其他运算符也是一样的道理。这样写更加简洁
五、单目操作符
符号:
! 逻辑反操作
& 取地址
sizeof 操作数的类型长度(以字节为单位)
~ 对一个数的二进制按位取反
– 前置、后置–
++ 前置、后置++
单个 * 间接访问操作符(解引用操作符)
单个 - 负值
单个 + 正值
注意:后面这三个符号在此处与加、减、乘的使用不同
1. !
! 逻辑反操作 一般用于判定中,如:!=
2.&
& 取地址 一般与* 间接访问操作符(解引用操作符) 一起用
int a = 10;
int*b = &a;//a变量的地址
//*b 对b进行解应用,通过b中存放的地址,找到指向的对象
int arr[10] = { 0 };
int(*c)[10]= &arr;//数组arr的地址
3.sizeof
sizeof 是用与计算变量或者类型所创建变量的大小的操作符,单位是字节
int a = 4;
printf("%zd",sizeof(a));
printf("%zd", sizeof a );
printf("%zd",sizeof(int));
int arr[10] = { 0 };
printf("%zd",sizeof(arr));//计算数组的大小
//最后大小为40,因为一个整数有4个字节
sizeof 计算的结果是size_t 类型的;size_t 是无符号整形,对size_t 类型数据的打印,可以使用%zd
sizeof 后面的括号中写的不是类型时,括号可以省略(所有函数后面的的括号都不可以省略因为函数至少需要一个操作符即() ,说明sizeof不是函数,是一个操作符
sizeof与数组:
void Test1(int arr[])
{
printf("%zd\n", sizeof(arr));
}
void Test2(char brr[])
{
printf("%zd\n", sizeof(brr));
}
int ar[10] = { 0 };
char br[10] = { 0 };
printf("%zd\n", sizeof(ar));
//传递的是数组名,即为数组首元素的地址,也就是一个指针
//在32位环境下是4个字节,64位环境下是8个字节
printf("%zd\n", sizeof(br));
Test1(ar);
Test2(br);
x86环境下
x64环境下
4.~
~ 对一个数的二进制按位取反
与位操作符一样,是对于补码进行操作,这里是进行取反
例如:
int a = 7;
int b = ~a;
//a的补码:00000000000000000000000000000111
//b的补码:11111111111111111111111111111000//按位取反
//b的反码:11111111111111111111111111110111
//b的原码:10000000000000000000000000001000
printf("%d",b);
常用于:
//将a的第四个二进制位改为1,然后将a复原到c中
int a = 7;
int b = a | (1 << 4);
int c = b & (~(1 << 4));
//a的补码:00000000000000000000000000000111
//1 << 4 :00000000000000000000000000001000
//a的补码:00000000000000000000000000001111
//~(1<<4);11111111111111111111111111110111
//c的补码:00000000000000000000000000000111
printf("%d %d %d",a,b,c);
5. ++ 与 - -
只要是++ 操作都是自增1,但区别是:
前置的++ 是先进行+1 后使用
后置的++ 是先使用 后+1
例如:
int a = 1;
int b = ++a;//a=a+1 b=a;
int d = 1;
int c = d++;//c=d d=d+1;
printf("a=%d b=%d c=%d d=%d",a,b,c,d);
//前置或者后置++ 与a,d无关,他们都会+1,只与接收的有关
只要是- - 操作都是自减1,但区别是:
前置的- - 是先进行-1 后使用
后置的- - 是先使用 后-1
与 ++ 的用法基本一致
例如:
//前置++和--
int a = 10;
int x = ++a;//x=11
//先对a进行自增,然后再使用a,也就是表达式的值是a自增之后的值。x为11。
int y = --a;//y=11-1=10
//先对a进行自减,然后对使用a,也就是表达式的值是a自减之后的值。y为10;
return 0;
//后置++和--
int a = 10;
int x = a++;//x=10
//先对a先使用,再增加,这样x的值是10;之后a变成11;
int y = a--;y=11
//先对a先使用,再自减,这样y的值是11;之后a变成10;
return 0;
6.例题:
六、关系操作符
符号:
=
<
<=
!= 用于测试“不相等”
== 用于测试“相等”
这些操作符一般都用于判定中,比较常用也比较简单,没什么可讲的,但是我们要注意一些运算符使用时候的陷阱。
警告:
在编程的过程中== 和=不小心写错,导致的错误。(比如if语句中的相等是 == )
七、. 逻辑操作符
符号:
&& 逻辑与
|| 逻辑或
在判段中
(1)
逻辑与:两个都满足才执行
逻辑或:两个中有一个满足就执行
(2)
&& :当左边的条件为假时,右边的不用执行了
|| :当左边的条件为真时,右边就不需要执行了
例如:
int i = 10;
if (i > 5 && i < 15)//两者都满足才执行
{
printf("%d",i);
}
if (i > 100 || i < 15)//两者只要有一个满足就执行
{
printf("%d", i);
}
例题:
//打印出的结果是多少?
int e = 0, a = 0, b = 2, c = 3, d = 4;
e = a++ && ++b && c++;
printf("%d %d %d %d %d",a,b,c,d,e);
解析:
int e = 0, a = 0, b = 2, c = 3, d = 4;
e = a++ && ++b && c++;
//首先判段a++,a++执行,先使用后++;
//由于先使用,a=0,为假,已有一个条件不满足,后面的不执行
printf("%d %d %d %d %d",a,b,c,d,e);
例题2:
//打印出的结果是多少?
int e = 0, a = 1, b = 2, c = 3, d = 4;
e = a++ && ++b && c++;
printf("%d %d %d %d %d",a,b,c,d,e);
解析:
int e = 0, a = 1, b = 2, c = 3, d = 4;
e = a++ && ++b && c++;
//首先判段a++,a++执行,先使用后++;
//由于先使用,a=1,为真,后面的判段,也为真,都执行
//e中的三个条件都为真,所以e也为真,值为1
printf("%d %d %d %d %d",a,b,c,d,e);
例题3:
//打印出的结果是多少?
int e = 0, a = 1, b = 2, c = 3, d = 4;
e = a++ || ++b || c++;
printf("%d %d %d %d %d",a,b,c,d,e);
解析:
int e = 0, a = 1, b = 2, c = 3, d = 4;
e = a++ || ++b || c++;
//首先判段a++,a++执行,先使用后++;
//由于先使用,a=1,为真,已满足条件,后面的不用执行
//e中的已有一个条件为真,所以e也为真,值为1
printf("%d %d %d %d %d",a,b,c,d,e);
区分逻辑与和按位与
区分逻辑或和按位或
1&2----->0
1&&2---->1
1|2----->3
1>||2---->1
八、 条件操作符
符号:exp1 ? exp2 : exp3
当表达式1(即问号前的表达式)为真时,执行表达式2,表达式3不执行。
当表达式1(即问号前的表达式)为假时,执行表达式3,表达式2不执行。
九、 逗号表达式
符号:exp1, exp2, exp3, …expN
逗号表达式,就是用逗号隔开的多个表达式。
逗号表达式,从左向右依次执行。整个表达式的结果是最后一个表达式的结果。
例如:
int a = 0;
int i = 0;
while (i++, i < 5)//逗号表达式,会从左往右执行,所以i++会执行;
//以最后一个表达式为结果,所以结果为while(i<5)
{
a++;
}
十、.下标引用、函数调用和结构成员
1.下标引用
- [ ] 下标引用操作符
操作数:一个数组名 + 一个索引值
例如:
int arr[10];//创建数组
arr[1] = 10;//实用下标引用操作符。
//[ ]的两个操作数是arr和9
2. 函数调用操作符
()函数调用操作符
接受一个或者多个操作数:第一个操作数是函数名,剩余的操作数就是传递给函数的参数。
比如:
void a()
{
printf("a\n");
}
void b(const char *b)
{
printf("%s\n", b);
}
int main()
{
test1(); //实用()作为函数调用操作符。
test2("hello");//实用()作为函数调用操作符。
return 0;
}
3. 访问一个结构的成员
符号:
. 结构体.成员名
-> 结构体指针->成员名
例如:
struct Stu
{
char name[10];
int age;
char sex[5];
double score
}
void set_age1(struct Stu a)
{
a.age = 18;
}
void set_age2(struct Stu* b)
{
b->age = 18;//结构成员访问
}
int main()
{
struct Stu a;
struct Stu* b = &stu;//结构成员访问
a.age = 20;//结构成员访问
set_age1(a);
b->age = 20;//结构成员访问
set_age2(b);
return 0;
}
总结
本次关于操作的教程以完,希望能对大家有所帮助。