• C语言第十六课:操作符详解(下)——逗号表达式、下标引用、函数调用、结构成员操作符与操作符属性


    目录

    前言:

    一、逗号表达式(exp1,exp2,exp3,...,expN):

    二、下标引用、函数调用和结构成员[ ]、( )、. 、->:

            1.下标引用操作符[ ]:

            2.函数调用操作符( ):

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

            ①.结构体成员访问操作符 .:

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

    三、操作符属性:

    四、总结:


    前言:

            前面我们对操作符进行了简单的分类:

    算术操作符移位操作符位操作符
    赋值操作符单目操作符关系操作符
    逻辑操作符条件操作符逗号表达式
    下标引用、函数调用和结构成员

            在上一篇文章中我们学习了单目、关系、逻辑与条件操作符的相关知识。本文我将继续按照顺序,带领小伙伴们一起学习操作符最后关于逗号表达式下标引用函数调用结构成员这些部分。

    一、逗号表达式(exp1,exp2,exp3,...,expN):

            逗号表达式,就是用逗号隔开的多个表达式。

            各位小伙伴们一起来看看下面的代码,想一想它的最终结果会是什么,会如何在屏幕上进行打印呢:

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include
    3. int main()
    4. {
    5. int a = 1;
    6. int b = 2;
    7. int c = (a > b, a = b + 10, a, b = a + 1);
    8. printf("变量 c 的值为:%d\n", c);
    9. return 0;
    10. }

            答案是它会在我们的屏幕上打印出“变量 c 的值为:13”。那么变量c的值为什么会是13呢?逗号表达式又是如何作用的呢?

            逗号表达式的作用方式为:整个逗号表达式从左向右依次执行整个表达式的结果是最后一个表达式的结果

            即上述代码的执行流程为,首先判断a与b的大小,判断为假,但是判断后没有进行赋值变量a与变量b的值没有发生变化,继续向右执行;接着计算了b+10的值并将该值赋给了a,此时a的值变为12,继续向右执行;最后计算了b=a+1的值并将该值赋给了b,此时b的值变为了13;这时,整个逗号表达式内的各个表达式就执行结束了,而此时逗号表达式的最后一个表达式的结果为13,则将最后一个表达式的值13作为整个逗号表达式的结果赋给了c,所以在我们的屏幕上进行反馈打印时,打印出的变量c的值为13。

            逗号表达式也可用于分支、循环语句的条件判断中:

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include
    3. int main()
    4. {
    5. int a = 5;
    6. int b = 3;
    7. int c = 1;
    8. int d = 0;
    9. int i = 10;
    10. for (i = 0; i < (i + 20, b = 1 - 5, a = b - 1, c = 3); i++)
    11. {
    12. if (a = b + 1, c = a / 2, d > 0)
    13. {
    14. printf("D > 0\n");
    15. }
    16. else
    17. {
    18. printf("D <= 0\n");
    19. }
    20. }
    21. return 0;
    22. }

            这段代码中,首先进行循环条件判断中 i 的范围限制使用了逗号表达式,且逗号表达式从左向右依次执行后,最后一个表达式的结果为3,故整个逗号表达式的结果为3,也就是相当于与此时循环语句可以理解为:

    for (i = 0; i < 3; i++);

            即整个循环语句将会循环执行三次。

            接着,在循环语句内部,分支语句的判断条件同样可以使用逗号表达式,逗号表达式的最后一个表达式为d>0,判断为假,即整个逗号表达式的判断结果为假,执行else语句。

            所以整段代码的执行结果为循环执行三次else打印

            那么逗号表达式有什么实际作用呢?我们来看下面这样的代码:

    1. a = get_val();
    2. count_val(a);
    3. while( a > 0 )
    4. {
    5. //业务处理
    6. a = get_val();
    7. count_val(a);
    8. }

            这样的代码(假代码,仅研究形式不研究功能)理论上的功能是完备的,但是在书写方法上略显冗余,在需求功能更多时代码将会占用大量的空间,我们可以通过使用逗号表达式将其进行简化

    1. while (a = get_val(), count_val(a), a > 0)
    2. {
    3. //业务处理
    4. }

            采用这样的形式,可以将原本冗杂的写法,改写的更为简洁,大幅度提高我们书写代码的效率

    二、下标引用、函数调用和结构成员[ ]、( )、. 、->:

            1.下标引用操作符[ ]:

            下标引用操作符可是各位小伙伴们的老朋友了,这个操作符,在我们数组的学习和使用中可谓是符不离手了。它的使用没有什么难度,我们在这里简单对该操作符进行回顾即可。

            下标引用操作符的操作数有两个:一个数组名 + 一个索引值

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include
    3. int main()
    4. {
    5. //创建数组:
    6. int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    7. //使用下标引用操作符数组元素:
    8. int b = arr[9];
    9. //操作符[ ]的两个操作数为:数组名arr和索引值9
    10. printf("arr[9]中存放的数据元素为:%d\n", b);
    11. return 0;
    12. }

            在使用时,下标引用操作符表示从下标引用以操作符的操作数数组名为名的数组中,访问以其索引值为下标的数据元素。数组的下标从0开始,故下标为9的数据元素应当为数组中的第十个元素

            2.函数调用操作符( ):

            函数调用操作符我们同样也很熟悉,通过对函数的使用,可以使我们的程序各部分功能实现模块化开发,大幅度提升了我们代码的可读性与可移植性,并且便于我们通过一些手段对我们的功能代码实现隐藏。在这里我们也对其进行一个回顾即可:

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include
    3. //test1函数定义:
    4. void test1()
    5. {
    6. printf("Hi!\n");
    7. }
    8. //test2函数定义:
    9. void test2(const char* str)
    10. {
    11. printf("%s\n", str);
    12. }
    13. int main()
    14. {
    15. test1();
    16. //调用函数test1
    17. //函数调用操作符的操作数可以是一个,此处为函数名test1
    18. test2("Thanks!");
    19. //调用函数test2
    20. //函数调用的操作数也可以是两个或多个,此处为函数名test2与函数参数字符串"Thanks!"
    21. return 0;
    22. }

            即函数调用操作符的操作数可以是一个也可以是两个或多个第一个操作数为函数名剩余操作数为传递给函数的参数

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

            结构体我们目前还没有讲到,但对于当前操作符的讲解影响不大,且由于结构体部分的知识较为复杂,我将会在后面单独为各位小伙伴们进行讲解。此处我们只研究其中需要用到的两个成员访问操作符

            ①.结构体成员访问操作符 .:

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include
    3. //定义结构体Book:
    4. struct Book
    5. {
    6. //结构体成员1:字符串书名
    7. char name[20];
    8. //结构体成员2:字符串作者
    9. char author[30];
    10. //结构体成员3:整形价格
    11. int price;
    12. };
    13. int main()
    14. {
    15. //结构体使用:struct+结构体名+结构体成员名={结构体成员属性}
    16. struct Book book1 = { "銮同学C语言","銮同学",0 };
    17. //结构体成员访问:结构体成员名.结构体成员属性
    18. printf("《 %s 》作者:%s 价格:%d\n", book1.name, book1.author, book1.price);
    19. return 0;
    20. }

            它的编译运行结果:

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

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include
    3. //定义结构体Book:
    4. struct Book
    5. {
    6. //结构体成员1:字符串书名
    7. char name[20];
    8. //结构体成员2:字符串作者
    9. char author[30];
    10. //结构体成员3:整形价格
    11. int price;
    12. };
    13. void print(struct Book* p)
    14. {
    15. //结构体成员访问:结构体成员名.结构体成员属性
    16. printf("《 %s 》作者:%s 价格:%d\n", (*p).name, (*p).author, (*p).price);
    17. //结构体成员访问:结构体指针->结构体成员属性
    18. printf("《 %s 》作者:%s 价格:%d\n", p->name, p->author, p->price);
    19. }
    20. int main()
    21. {
    22. //结构体使用:struct+结构体名+结构体成员名={结构体成员属性}
    23. struct Book book1 = { "銮同学C语言","銮同学",0 };
    24. //结构体成员传址调用
    25. print(&book1);
    26. return 0;
    27. }

            它的编译运行结果:

    三、操作符属性:

            在复杂表达式中进行求值时,有三个影响因素:

            1.操作符的优先级

            2.操作符的结合性

            3.是否控制求值顺序

            即在执行求值计算时,两相邻操作符应当先执行哪一个?这个问题的答案是,取决于他们的优先级若优先级相同则取决于他们的结合性

    表中操作符优先级从上到下依次减弱(lexp表示左表达式,rexp表示右表达式)
    操作符描述用法示例结果类型结合性是否控制求值顺序
    ()聚组(表达式)与表达式相同N-A
    ()函数调用rexp(rexp,...);rexpL-R
    [ ]下标引用rexp[rexp]lexpL-R
    .访问结构成员lexp.member_namelexpL-R
    ->访问结构指针成员rexp->member_namelexpL-R
    ++后缀自增lexp++rexpL-R
    --后缀自减lexp--rexpL-R
    !逻辑反!rexprexpR-L
    ~按位取反~rexprexpR-L
    +单目,表示正值+rexprexpR-L
    -单目,表示负值-rexprexpR-L
    ++前缀自增++rexprexpR-L
    --前缀自减--rexprexpR-L
    *间接访问*rexplexpR-L
    &取地址&lexprexpR-L
    sizeof以字节计算长度sizeof rexp/(类型)rexpR-L
    (类型)强制类型转换(类型)rexprexpR-L
    *乘法rexp*rexprexpL-R
    /除法rexp/rexprexpL-R
    %整数求余rexp%rexprexpL-R
    +加法rexp+rexprexpL-R
    -减法rexp-rexprexpL-R
    <<左移位rexp<rexpL-R
    >>右移位rexp>>rexprexpL-R
    >大于rexp>rexprexpL-R
    >=大于等于rexp>=rexprexpL-R
    <小于rexprexpL-R
    <=小于等于rexp<=rexprexpL-R
    ==等于rexp==rexprexpL-R
    !=不等于rexp!=rexprexpL-R
    &按位与rexp&rexprexpL-R
    ^按位异或rexp^rexprexpL-R
    |按位或rexp|rexprexpL-R
    &&逻辑与rexp&&rexprexpL-R

    ||

    逻辑或rexp||rexprexpL-R
    ?:条件操作符rexp?rexp:rexprexpN-A
    =赋值lexp=rexprexpR-L
    +=以...加lexp+=rexprexpR-L
    -=以...减lexp-=rexprexpR-L
    *=以...乘lexp*=rexprexpR-L
    /=以...除lexp/=rexprexpR-L
    %=以...取模lexp%=rexprexpR-L
    <<=以...左移lexp<<=rexprexpR-L
    >>=以...右移lexp>>=rexprexpR-L
    &=以...与lexp&=rexprexpR-L
    ^=以...异或lexp^=rexprexpR-L
    |=以...或lexp|=rexprexpR-L
    ,逗号表达式rexp,rexprexpL-R

    四、总结:

            到这里,关于字符串的知识的介绍就全部告一段落了,各位小伙伴们私下里应当尽可能的多去尝试,多去练习,从而巩固知识,磨练技术,达到真正提升个人代码书写能力的目的。

            希望各位小伙伴们能从加上今天的三篇关于字符串的应用详解中有所收获,同时能为各位小伙伴们的学习起到一些帮助我便也心满意足了。实力的来源不是胜利,唯有奋斗才能增强实力,当你历经苦难而不气馁,那就是实力!

            新人初来乍到,辛苦各位小伙伴们动动小手,三连走一走 ~ ~ ~  最后,本文仍有许多不足之处,欢迎各位看官老爷随时私信批评指正!

  • 相关阅读:
    如何设计性能优良的mysql索引?
    QT中启动窗口QSplashScreen的使用
    商城系统需求分析
    Java面试题:解释死锁的概念,给出避免死锁的常见策略。你能给我一个具体的例子吗?
    没有Web.xml文件Tomcat是如何获取应用配置信息的?
    15.Xaml StackPanel控件 布局控件
    IDM(Internet Download Manager)2024中文版下载工具软件
    Springboot3 + knife4j(springdoc) 框架整合
    导数差分近似公式总结
    【字符串】求解方程 数学
  • 原文地址:https://blog.csdn.net/weixin_59392935/article/details/128142123