小工具知识网

当前位置: 首页 > 行业知识 > C语言操作符

行业知识

C语言操作符

2026-11-06 14:07:52 来源:互联网转载

文章目录

  • 1:算术操作符
  • 2:移位操作符(移动的是二进制序列中的补码)
    • 2.1:知识补充(原码,反码,补码与二进制)
    • 2.2:左移操作符()
      • 2.2.1:逻辑右移
      • 2.2.2:算术右移
      • 3:位操作符(运算用的是二进制位的补码)
        • 3.1:按位与操作符(&)
        • 3.2:按位或操作符(|)
        • 3.3:按位异或操作符(^)
        • 4.赋值操作符
          • 4.1:复合赋值符
          • 5:单目操作符
            • 5.1:逻辑反操作符(!)
            • 5.2:正值,负值操作符(+ -)
            • 5.3:取地址操作符和解引用操作符(& *)
            • 5.4 sizeof操作符
            • 5.5:按位取反操作符(操作的是补码)
            • 5.6:++,--操作符
            • 5.7:强制类型转换操作符
            • 6:关系操作符
            • 7:逻辑操作符
              • 7.1:逻辑与操作(&&)
              • 7.2:逻辑或操作(| |)
              • 8.条件操作符(三目操作符)
              • 9:下标引用、函数调用和结构体成员访问操作符
                • 9.1:下标引用
                • 9.2:函数调用操作符
                • 9.3:结构体成员访问
                • 10:操作符的属性
                  • 10.1优先级
                  • 10.2结合性
                  • 11:表达式求值
                    • 11.1:整型提升
                      • 11.1.1整型提升的意义:
                      • 11.1.2:如何进行整型提升
                      • 11.2:算术转换
                      • 11.3:问题表达式解析
                        • 11.3.1:表达式1
                        • 11.3.2:表达式2
                        • 11.3.3:表达式3
                          嘻嘻,家人们,今天咱们来详解C语言中的操作符,好啦,废话不多讲,开干!

                          1:算术操作符

                          算术操作符呢其实就是我们日常生活中常见的加减乘除还有取余,这里博主就不具体展开讲了,就针对这些操作符中的小注意事项来进行讲解。

                          +   -   *(乘法)  /(除法)   %(取余)
                          • (1):除了%操作符以外,其他的几个操作符都可以作用于整数和浮点数。
                          • (2):对于/操作符,如果两个操作符都为整数,则执行整数除法(即只保留整数部分,去除小数部分),而只要存在浮点数执行的就是浮点数除法。
                          • (3):%操作符的两个操作数必须为整数,返回的是整除之后的余数。
                            #define  _CRT_SECURE_NO_WARNINGS#include int main(){//得到的是小数,但是是放入整型数据,因此得到的是3printf("7   / 2    = %d\n", 7 / 2);printf("7.0 / 2.0  = %d\n", 7.0 / 2.0);/**只要浮点数存在,那么执行的就是浮点数除法*/printf("7.0 / 2    = %lf\n", 7.0 / 2);printf("7.0 / 2.0  = %lf\n", 7.0 / 2.0);//%操作符的两个操作数必须为整数,返回的是整数之后的余数printf("7   %%  2   = %d\n", 7 % 2);return 0;}

                            2:移位操作符(移动的是二进制序列中的补码)

                            2.1:知识补充(原码,反码,补码与二进制)

                            在讲移位操作符之前,首先博主得补充些小知识,原码,反码和补码与二进制的相关知识

                            在日常生活中我们经常能够听到2进制、8进制、10进制、16进制的讲法,那是什么意思呢?其实2进制、8进制、10进制、16进制是数值的不同表示形式而已。拿具体的数字15来举例。

                            (1):15的2进制:1111

                            (2):15的8进制:17

                            (3):15的10进制:15

                            (4):15的16进制:F

                            博主重点介绍二进制,首先还是得从10进制讲起,10进制就是我们在日常生活中经常使用的,10进制数字有这两种特点:

                            (1):10进制中满10进1

                            (2):10进制的数字每一位都是0~9的数字组成。

                            那么其实二进制也是一样的,

                            (1):二进制中满2进1。

                            (2):二进制的数字每一位都0~1的数字组成。

                            了解了二进制相关的概念后,接下来博主将讲解原码、反码、补码

                            整数的2进制表示方法有三种,即原码,反码和补码

                            三种表示方法均有符号位和数值位两部分,符号位都是用0表示"正",用1表示"负",而数值位最高位的一位是被当做符号位,剩下的都是数值位。

                            正整数的原、反、补码都相同

                            负整数的三种表示方法各不相同

                            (1):原码:直接将数值按照正负数的形式翻译成⼆进制得到的就是原码。

                            (2):反码:符号位不变,其他位依次按位取反就可以得到反码。

                            (3):补码:反码+1就得到补码。

                            对于无符号数整数来说,没有符号位,所有位均位有效位。

                            2.2:左移操作符(int m = 7;int n = m /*-7 原码:10000000000000000000000000000111 反码:11111111111111111111111111111000 补码:11111111111111111111111111111001*/int m = -7;/* * 左移一位之后补码:11111111111111111111111111110010反码:11111111111111111111111111110001原码:10000000000000000000000000001110*/int n = m /*-7 原码:10000000000000000000000000000111 反码:11111111111111111111111111111000 补码:11111111111111111111111111111001*/int m = -7;int n = m 1;/*补码:01111111111111111111111111111100反码:01111111111111111111111111111011原码:00000000000000000000000000000100*/printf("m = %d\n", m);printf("n = %d\n", n);return 0;}

                            如果是按照逻辑右移的方式来进行移位的话,-7在右移一位之后,应该会变成4。

                            2.2.2:算术右移

                            #define  _CRT_SECURE_NO_WARNINGS#include int main(){/*-7 原码:10000000000000000000000000000111 反码:11111111111111111111111111111000 补码:11111111111111111111111111111001*/int m = -7;int n = m >> 1;/*补码:11111111111111111111111111111100反码:11111111111111111111111111111011原码:10000000000000000000000000000100*/printf("m = %d\n", m);printf("n = %d\n", n);return 0;}

                            若按照算术右移的方式,在右边补上符号位,左边丢弃,在上面我们讲解过,对于有符号整数,最高位为符号位,0代表正,1代表负,因此-7在进行算术右移的时候应该补1,按照算术右移的方式,-7在算术右移一位之后,应该会变成-4。

                            通过观察结果可知,博主使用的vs2022在这里采用的是算术右移,因此n的是为-4。

                            (1)对于移位操作符,不要移动负数位,这个标准是未定义的。

                            (2)移位操作符的操作数只能是整数。

                            3:位操作符(运算用的是二进制位的补码)

                            位操作符有三种,分别是

                            > 按位与--------- &

                            按位或--------- |

                            按位异或------ ^

                            我们分别来看这三个操作符。

                            3.1:按位与操作符(&)

                            首先是按位与操作符,按位与操作符用一句话来总结就是**"同时为1则1",**可能家人们对这句话不是特别理解,我们来看一段代码。
                            #define  _CRT_SECURE_NO_WARNINGS#include int main(){int a = 5;int b = -3;int c = a & b;printf("%d\n", c);return 0;}
                            将5和-3进行按位与操作然后赋值给c,此时c的值为5,那么为什么为5呢?博主带着大家来解析一下。

                            在上面博主有讲到,按位与操作符同样计算的也是二进制位中的补码,因此首先我们将5和-3的补码表示出来。

                            -3:原码:10000000000000000000000000000011   反码:11111111111111111111111111111100   补码:11111111111111111111111111111101 5:补码:00000000000000000000000000000101 c:补码:00000000000000000000000000000101

                            将5和-3的补码表示出来后,接下来就要对每一位进行按位与操作,什么叫同时为1则为1呢,譬如在这里,5的二进制位的最高位为0,-3的二进制为的最高位为1,由于不同时为1,那么在进行按位与操作后,因此c的二进制位的最高位得到的是0。再来,5的二进制位的最低位是1,-3的二进制位的最低位也是1,因此c的二进制位的最低位为1。其他的二进制位同样按照这种方式进行计算。在进行计算后,得到c的补码,我们发现最高位是0,因此c是正整数,那么原、反、补码相同,将其二进制转换为十进制得到的就是5。

                            3.2:按位或操作符(|)

                            讲完了按位与操作符之后,接下来再讲讲按位或操作符,按位或操作符用一句话总结就是**"其中为1则为1"。**,我们还是来看一段代码。
                            #define  _CRT_SECURE_NO_WARNINGS#include int main(){int a = 5;int b = -3;int c = a | b;printf("%d\n", c);return 0;}
                            将5和-3进行按位或操作然后赋值给c,此时c的值为-3,那么为什么为-3呢?博主带着大家来解析一下,同样我们将5和-3的补码表示出来。
                            -3:原码:10000000000000000000000000000011   反码:11111111111111111111111111111100   补码:11111111111111111111111111111101 5:补码:00000000000000000000000000000101 c:补码:11111111111111111111111111111101   反码:11111111111111111111111111111100   原码:10000000000000000000000000000011

                            将5和-3的补码表示出来后,接下来就要对每一位进行按位或操作,什么叫其中为1则为1呢?譬如在这里,5的二进制位的最高位为0,-3的二进制为的最高位为1,由于存在1,那么在进行按位或操作后,因此c的二进制位的最高位得到的是1。再来,5的二进制位的最低位是1,-3的二进制位的最低位也是1,因此c的二进制位的最低位为1。其他的二进制位同样按照这种方式进行计算。在进行计算后,得到c的补码,我们发现最高位是1,也就是说此时变量c为负整数,因此我们要求出其原码,补码求出原码的方式:**(1):符号位不变,补码减1得到反码;(2):符号位不变,数值位进行取反得到原码。**得到原码后,将其转换10进制数得到的就是-3啦!

                            3.3:按位异或操作符(^)

                            接下来我们再看一个位操作符,按位异或操作符,按位异或操作符用一句话来总结就是"相同为0,相异为1"。我们直接看下面这段代码。
                            #define  _CRT_SECURE_NO_WARNINGS#include int main(){int a = 5;int b = -3;int c = a ^ b;printf("%d\n", c);return 0;}

                            将5和-3进行按位异或操作然后赋值给c,此时c的值为5,那么为什么为-8呢?博主带着大家来解析一下。

                            -3:原码:10000000000000000000000000000011   反码:11111111111111111111111111111100   补码:11111111111111111111111111111101 5:补码:00000000000000000000000000000101 c:补码:11111111111111111111111111111000   反码:11111111111111111111111111110111   原码:10000000000000000000000000001000

                            将5和-3的补码表示出来后,接下来就要对每一位进行按位或操作,什么叫相同为0,相异为1呢?譬如在这里,5的二进制位的最高位为0,-3的二进制为的最高位为1,0和1不是相同的,那么在进行按位异或操作后,因此c的二进制位的最高位得到的是1。再来,5的二进制位的最低位是1,-3的二进制位的最低位也是1;1和1是相同的,因此c的二进制位的最低位为0。其他的二进制位同样按照这种方式进行计算。在进行计算后,得到c的补码,我们发现最高位是1,也就是说此时变量c为负整数,因此我们要求出其原码,得到原码后,将其转换10进制数得到的就是-8啦!

                            • a ^ a = 0;
                            • 0 ^ a = a;

                              PS:对于位操作符,他们的操作数也同样必须为整数。

                              4.赋值操作符

                              赋值操作符是一个很棒的操作符,他可以让你得到一个你之前不满意的值,也就是你可以给自己重新赋值。
                              #define  _CRT_SECURE_NO_WARNINGS#include int main(){//初始化体重为120int weight = 120;//不满意就赋值weight = 90;return 0;}

                              4.1:复合赋值符

                                  +=-=*=/=%=>>=int a = 10;//等价于 a = a + 1a += 1;int b = 5;//等价于 b = b int data = 0;int b = !data;printf("%d\n", b);if (b){printf("hello world\n");}return 0;}int a = -5;int b = -a;int c = +a;printf("b = %d,c = %d\n", b, c);return 0;}int a = 10;//定义指针变量p,存储a的地址int* p = &a;//对p进行解引用操作,*p是通过p中存放的地址,找到所指的对象,*p其实就是a*p = 20;printf("a  = %d\n", a);printf("*p = %d\n", *p);printf("p  =%p\n", p);return 0;}/*sizeof是计算类型创建变量或者变量的大小,单位为字节sizeof计算的结果是size_t类型的size_t是无符号整型的对size_t类型的数据进行打印,可以使用%zd*/int a = 10;printf("%zd\n", sizeof(a));printf("%zd\n", sizeof(int));printf("%zd\n", sizeof a);return 0;}int a = 0;int b = ~a;printf("%d\n", b);return 0;}int a = 5;//先使用,后+1int b = ++a;//a = 6;b = 6 printf("前置++后:a = %d,b = %d\n", a,b); b = a++;//b = 6,a = 7printf("后置++后:a = %d,b = %d\n",a,b);return 0;}//强制类型转换为整型;int a = (int)3.14;printf("%d",a)return 0;}int i = 0,a = 0, b = 2, c = 3, d = 4;i = a++ && ++b && d++;printf("a = %d,b = %d, c = %d, d = %d\n", a, b, c, d);printf("i = %d\n", i);return 0;}int i = 0, j, a = 0, b = 2, c = 3, d = 4;j = a++ || ++b || d++;printf("a = %d,b = %d,c = %d,d = %d\n", a, b, c, d);printf("j = %d\n", j);return 0;}int a = 0;int b = 0;int max = 0;scanf("%d %d", &a, &b);max = a  b ? a : b;printf("max = %d\n", max);return 0;}int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };//[]下标引用操作符printf("%d", arr[0]);return 0;}return x * y;}int main(){int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };//()函数调用操作符printf("hello world\n");int a = 0;int b = 0;scanf("%d %d", &a, &b);//()函数调用操作符int value = Product(a, b);printf("%d\n", value);return 0;}char name[20];int  price;};void Print(struct book * b){//通过*解引用操作,找到所指的对象printf("%s %d\n", (*b).name, (*b).price);//结构体指针变量-成员名printf("%s %d\n", b-name, b->price);}int main(){struct book b = { "C++书籍",25 };//结构体.成员,找到所指的对象printf("%s %d\n", b.name, b.price);Print(&b);return 0;}

                              10:操作符的属性

                              C语言操作符有三个重要的属性影响因素
                              • 操作符的优先级
                              • 操作符的结合性
                              • 是否控制求值顺序

                                10.1优先级

                                优先级指的是,如果一个表达式包含多个运算符,哪个运算符应该优先执行。各种运算符的优先级是不一样的。

                                3 + 4 * 5;

                                上⾯⽰例中,表达式 3 + 4 * 5 ⾥⾯既有加法运算符( + ),⼜有乘法运算符( * )。由于乘法的优先级⾼于加法,所以会先计算 4 * 5 ,⽽不是先计算 3 + 4 。

                                10.2结合性

                                如果两个运算符优先级相同,优先级没办法确定先计算哪个了,这时候就看结合性了,则根据运算符是左结合,还是右结合,决定执⾏顺序。大部分运算符是左结合(从左到右执行),少数运算符是右结合(从右到左执行),比如赋值运算符

                                5 * 6 / 2;

                                上面示例中,*和/的优先级相同,它们都是左结合运算符,所以从左到右执行,先计算 5 * 6,再计算6 / 2。

                                上图是C语言操作符的优先级顺序,uu们不需要全部记忆,只需要记住大概就好,在使用的时候如果忘记了查看表格即可!

                                11:表达式求值

                                11.1:整型提升

                                C语言中整型算术运算总是至少以缺省整型类型的精度来进行的。为了获得这个精度,表达式中的字符和短整型操作符在使用之前被转换为普通整型,这种转换称为整型提升。

                                11.1.1整型提升的意义:

                                表达式的整型运算要在CPU的相应运算器件内执行,CPU内整型运算器的操作数的字节长度一般就是Int的字节长度,同时也是CPU的通用寄存器的长度。

                                因此,即使两个char类型的相加,在CPU执行时实际上也要先转换为CPU内整型操作数的标准长度。

                                通用CPU是难以直接实现两个8byte直接相加运算(虽然机器指令中可能存在这种字节相加指令)。所以,表达式中各种长度可能小于int长度的整型值,都必须先转换为int或unsigned int,然后才能送入CPU去执行运算。

                                11.1.2:如何进行整型提升

                                1:有符号整数提升是按照变量的数据类型的符号位来进行提升的.

                                2:无符号数整型提升,高位补0.

                                #define  _CRT_SECURE_NO_WARNINGS#include int main(){char a = 5;char b = 126;char c = a + b;printf("%d\n", c);return 0;}
                                5:补码:00000000 00000000 00000000 00000101a:补码:00000101126:补码:00000000 00000000 00000000 01111110b:补码:01111110c:补码:10000011整型提升后c:补码:11111111 11111111 11111111 10000011  反码:11111111 11111111 11111111 10000010  原码:10000000 00000000 00000000 01111101

                                上述代码中,将5存放在char类型的变量a中,将126存放在char类型的变量b中,由于char类型只占1个字节即8个bit位,int类型占个4个字节,32个bit位,因此会发生截断,取其前8位存放;那么分别将5和126的补码表示出来,表示出来后,取前8位,分别得到变量a与变量b的补码,最后将其补码相加得到变量c的补码,在打印变量c时,使用的是%d,十进制整数占位符,因此会发生整型提升,那么怎么提升呢?我们已经得到了变量c的补码,char类型的数据是signed char 还是 unsigned char是不确定的,C语言没有明确指定,是取决于编译器的,博主当前使用的VS上,char 类型默认是signed char即有符号数,因此在整型提升时,按照其符号位来进行提升,由于C的符号位为1,因此在整型提升时,进行高位补1,补齐剩下的24个字节,在进行整型提升后,我们得到了补码,由于在打印时打印的是原码,因此我们求出其原码,最后将其转换为10进制的数就能得出c的值为-125。

                                11.2:算术转换

                                如果某个操作符的各个操作数属于不同的类型,那么除非其中一个操作数转换为另一个操作数的类型,否则操作就无法进行。下面的层次体系称为寻常算术转换

                                如果某个操作数的类型在上⾯这个列表中排名靠后,那么⾸先要转换为另外⼀个操作数的类型后执⾏运算。

                                11.3:问题表达式解析

                                11.3.1:表达式1

                                a * b + c * d + e * f;

                                上述表达式在计算的时候,由于*比+的优先级高,只能保证,的计算比+早,但是优先级并不能觉得第三个比第一个+早执行。那么就会如下两种情况的计算顺序。

                                11.3.2:表达式2

                                c + --c;

                                操作符的优先级只能决定自减–的运算在+的运算之前,但是我们并没有办法得知,+操作符的左操作数的获取在右操作数之前还是之后求值,所以结果是不可预测的。

                                11.3.3:表达式3

                                #include int fun(){    static int count = 1;    return ++count;}int main(){    int answer;    answer = fun() - fun() * fun();    printf("%d\n",answer);    return 0;}

                                上述代码虽然在大多数编译器上求得的结果是一样的,但是在表达式answer = fun() - fun() * fun()

                                中我们只能通过操作符的优先级得知:先算乘法,再算减法,函数的调用顺序无法通过操作符的优先级确定。

                                好啦,家人们,关于这块的相关细节知识,博主就讲到这里了,如果uu们觉得博主讲的不错的话,请动动你们滴的小手给博主点个赞,你们滴鼓励将成为博主源源不断滴动力!

上一篇:亲测有效,解决Can ‘t connect to local MySQL server through socket ‘ tmp mysql

下一篇:3ds服务器怎么进去?