C语言操作符总结

本文详细介绍了C语言中的各类操作符,包括算数操作符、移位操作符、位操作符等,并对每种操作符的功能和使用场景进行了具体分析。此外还探讨了操作符属性及其可能引发的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录:

一、操作符分类

  • 算数操作符:+ - * / %
  • 移位操作符:<< >>
  • 位操作符:& | ^
  • 赋值操作符:= += -= *= /= %= >>= <<= &= |= ^=
  • 单目操作符·:! - + & sizeof ~ -- ++ * (类型)
  • 关系操作符:> >= < <= != ==
  • 逻辑操作符:&& ||
  • 条件操作符:exp1 ? exp2 : exp3
  • 下表引用操作符、函数调用操作符、结构体成员访问操作符:[] () . ->

二、具体分析

2.1 算数操作符:+ - * / %

以上操作符分别为:加法、减法、乘法、除法、取模

取模操作符要求两个操作数都必须为整数,结果是整除后的余数。另外几个操作符可以用于整数和浮点数,但应注意计算中的类型转化。

  • 特别注意:除法操作 / ,当两个操作数都为整数进行整数除法,除此之外都进行浮点数除法。
2.2 移位操作符:<< >>

<< 左移操作符;>>右移操作符

不管是左移操作符还是右移操作符都是相对于整数而言,而且必须是整数类型,整数类型在内存中按其32位补码存放。

左移操作符:
这里写图片描述

对于右移操作符分为,算术移位和逻辑移位,具体情况因编译器而定,常见的编译器大都采用算术移位。

算术右移位:
这里写图片描述
逻辑右移位:
这里写图片描述

移位操作符不改变变量的原始值。

2.3 位操作符:& | ^
  • &:逻辑AND,同1为1,否则为0
  • |:逻辑OR,同0为0,否则为1
  • ^:逻辑XOR,相同为0,相异为1

    位操作符同样只适用于两个整形的操作数
    这里写图片描述
    这里写图片描述

2.4 赋值操作符:= += -= *= /= %= >>= <<= &= |= ^=

当需要改变变量的值时,就需要赋值操作符,复合赋值符实在原有赋值符的基础上为了简化代码而产生的。
这里写图片描述

2.5 单目操作符·:! - + & sizeof ~ -- ++ * (类型)

以上操作符分别为:逻辑反、负值、正值、取地址、求操作数的类型长度、对一个数的二进制按位取反、前置/后置–、前置/后置++、解引用操作符、强制类型转换

单目操作符表示其只有一个操作数。

  • (1)不同于 ~,C语言规定,0为假,非0为真,逻辑反可以改变其真假;而 ~ 是把操作数所对应二进制补码按位取反,0变1,1变0。
    这里写图片描述

  • (2)&取地址操作符

用于得到一个操作数在内存中的存放地址。

#include <stdio.h>
int main()
{
    int arr[10] = {0};
    printf("%p\n", arr);//数组名相当于首元素的地址
    printf("%p\n", arr+1);
    printf("%p\n", &arr);//&数组名相当于取出的是整个数组的地址
    printf("%p\n", &arr+1);
    return 0;
}

这里写图片描述
很明显,数组名+1,地址偏移了一个元素的大小,&数组名+1,地址偏移了整个数组的大小。

  • (3)通过sizeof求一个操作数的类型的大小,单位bit(sizeof不是一个函数,是一个操作符,其后的表达式不参与运算,是因为sizeof作为一个表达式,是在源文件编译期间处理,而其后如果有表达式,是需要在程序运行期间计算,所以表达式未计算)
#include <stdio.h>
int main()
{
    int a = 1;
    short b = 2;
    printf("%d\n",sizeof(b=a+3));
    printf("%d\n",a);
    printf("%d\n",b);
    return 0;
}

这里写图片描述

  • (4)前置++/– 先自加/减再使用;后置++/– 先使用后自加/减;指针的++/–与指针的类型有关(指针的类型决定了指针+/-1能走多远和解引用(*)能访问的内存大小)

  • (5)解引用操作符:通过一个指针,间接访问存放在该地址所对应内存上的变量。

  • (6)强制类型转换操作符:根据特殊需要,将精度高的操作数转化为精度小的操作数,会造成精度丢失。

2.6 关系操作符:> >= < <= != ==

用于比较两个操作数的大小,结果返回真假。

2.7 逻辑操作符:&& ||

&&:同真为真,否则为假;||:同假为假,否则为真
这里写图片描述
a && b && c(左图) ; a || b || c (右图)

一旦后面的表达式被跳过,将不再进行任何操作,因为前面的结果已经能够确定整个表达式的结果。

2.8 条件操作符:exp1 ? exp2 : exp3

如果表达式1的结果为真,则执行表达式2,为假执行表达式3。

if (a>b)
{
    max = a;
}
else
{
    max = b;
}
//上面的代码等价于底下的代码
max = (a>b) ? a : b;

同样如果表达式1为真,表达式3将不再执行;为假表达式1不再执行。求值顺序的改变会对关联变量的赋值产生影响,从而影响程序运行结果,需注意!
这里写图片描述

2.9 下表引用操作符、函数调用操作符、结构体成员访问操作符:[] () . ->
  • 下表引用操作符:[]
    下标引用操作符是一个双目操作符,它需要数组名+下标共同完成索引
#include <stdio.h>
int main()
{
    int arr[10] = {1234567890};
    //以下方式都可以成功调用数组中第五个元素
    printf("%d\n", arr[4]);
    printf("%d\n", *(arr+4)); 
    printf("%d\n", *(4+arr);
    printf("%d\n", 4[arr]); 
    return 0;
}
  • 函数调用操作符接受的操作数决定于函数的参数,参数为void时,只接受一个操作数,即函数名,参数为多个时,调用的操作数也相应增加。

  • 结构体成员访问操作符:. ->

. 是相对于结构体变量而言,-> 是相当于结构体指针而言

#include <stdio.h>
#include <string.h>

struct Stu
{
    char name[20];
    int age;
    float score;
};

int main()
{
    struct Stu s;
    struct Stu* ps = &s;

    strcpy(s.name, "zhangsan");
    s.age = 20;
    s.score = 55.0f;

    printf("%s %d %f\n", s.name, s.age, s.score);//通过结构体访问其成员
    printf("%s %d %f\n", ps->name, ps->age, ps->score);//通过结构体指针访问其成员
    return 0;
}

三、操作符属性及由其带来的问题

操作符的属性对复杂表达式的求值有三方面的影响:
(1)操作符的优先级
(2)操作符的结合性
(3)是否控制求值顺序

操作符描述结合性是否控制求职顺序
( )聚组不适用
( )函数调用L-R
[ ]下表引用L-R
.访问结构成员L-R
->访问结构指针成员L-R
++后置自加L-R
后置自减L-R
!逻辑反R-L
~按位取反R-L
+单目,表示正值R-L
-单目,表示负值R-L
++前置自加R-L
前置自减R-L
*间接访问R-L
&取地址R-L
sizeof取其长度,以字节表示R-L
(类型)类型转换R-L
*乘法L-R
/除法L-R
%整数取余L-R
+加法L-R
-减法L-R
<<左移位L-R
>>右移位L-R
>大于L-R
>=大于等于L-R
<小于L-R
<=小于等于L-R
==等于L-R
!=不等于L-R
&位与L-R
^位异或L-R
|位或L-R
&&逻辑与L-R
||逻辑或L-R
?:条件操作符不适用
=赋值R-L
,逗号L-R

上表是按操作符的优先级依次排列,对于一个复杂表达式,两个相邻操作符的执行顺序由它们的优先级决定,如果优先级相同,则再考虑结合性,而控制求值顺序的操作符仅有:逗号、&&、||、和?:四个,只要满足上面这三点,编译器可以对表达式的计算顺序任意决定,这便会产生问题:

a * b + c * d + e * f   

每个乘法只需保证在其相邻的加法执行前执行即可,则这个表达式的计算方式将不唯一,虽然在此式中不同的计算顺序对表达式的结果没有产生影响,但是如果变量的值在求解的过程中被重新赋值,求解路径不唯一结果将不唯一,如下:

#include <stdio.h>
int main()
{
    int a = 1;
    printf("%d\n",(++a)+(++a)+(++a));
    return 0;
}

这段代码将会在不同的编译器下产生不同的结果:
这里写图片描述
这里写图片描述
所以要避免这样代码的产生,以提高其跨平台性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值