12 三目运算符和逗号表达式 1 三目运算符 2 逗号表达式

1.1 用法

  • 三目运算符(a ? b : c)可以作为逻辑运算的载体

  • 规则:当 a 的值为真时,返回 b 的,否则返回 c 的

  • 示例

    • Demo

      #include <stdio.h>
      
      int main()
      {
          int a = 1;
          int b = 2;
          int c = 0;
          
          c = a < b ? a : b;
          
          (a < b ? a : b) = 3;
          
          printf("a = %d
      ",a);
          printf("b = %d
      ",b);
          printf("c = %d
      ",c);
          
          return 0;
      }
      
    • 编译

      • 分析:三目运算符返回的是一个值,而不是变量本身,不能作为左值
      test.c: In function ‘main’:
      test.c:11: error: lvalue required as left operand of assignment
      
  • 如果想利用三目运算符的返回值改变原先变量的值,那么可以返回地址,再对其解引用

    • Demo

      #include <stdio.h>
      
      int main()
      {
          int a = 1;
          int b = 2;
          int c = 0;
          
          *(a < b ? &a : &b) = 3;
          
          printf("a = %d
      ",a);  // 3
          printf("b = %d
      ",b);  // 2
          printf("c = %d
      ",c);  // 0
          
          return 0;
      }
      

1.2 返回类型

  • 三目运算符(a ? b : c)的返回值的类型

    • 通过隐式类型转换规则返回 bc 中的较高类型

    • bc 不能隐式转换到同一类型时,编译出错

    • Demo1:可以通过隐式转换

      #include <stdio.h>
      
      int main()
      {
          char c = 0;
          short s = 0;
          int i = 0;
          double d = 0;
          char* p = "str";
          
          printf("sizeof(c ? c : s) = %d
      ",sizeof(c ? c : s));  // 4:int
          printf("sizeof(i ? i : d) = %d
      ",sizeof(i ? i : d));  // 8:double
          
          return 0;
      }
      
    • Demo2:不能隐式转换到同一类型

      #include <stdio.h>
      
      int main()
      {
          char c = 0;
          short s = 0;
          int i = 0;
          double d = 0;
          char* p = "str";
          
          printf("sizeof(d ? d : p) = %d
      ",sizeof(d ? d : p));  // error
          
          return 0;
      }
      
    • 编译

      test.c: In function ‘main’:
      test.c:13: error: type mismatch in conditional expression
      

2 逗号表达式

2.1 用法

  • 逗号表达式是 C 语言中的“粘贴剂”

  • 逗号表达式用于将多个子表达式连接为一个表达式

  • 逗号表达式的值为最后一个子表达式的值

  • 逗号表达式中的前N-1个表达式可以没有返回值

  • 逗号表达式按照从左向右的顺序计算每个子表达式的值

  • 形式:exp1,exp2,exp3,...,expN

  • 示例:逗号表达式的使用

    • Demo1

      #include <stdio.h>
      
      int main()
      {
          int i = 0;
          while(i < 5)
              printf("i = %d
      ",i),
          i++;
          
          //等价于
          /*
          while(i < 5)
          {
              printf("i = %d
      ",i);
              i++;
          }
          */
          
          return 0;
      }
      
    • 编译运行

      i = 0
      i = 1
      i = 2
      i = 3
      i = 4
      
    • Demo2

      #include <stdio.h>
      
      void hello()
      {
          printf("Hello
      ");
      }
      
      int main()
      {
          int a[3][3] = {(0,1,2),(3,4,5),(6,7,8)};
          
          int i = 0;
          int j = 0;
          
          while(i < 5)
              printf("i = %d
      ",i),
          hello(),
          i++;
          
          for(i=0;i<3;i++){
              for(j=0;j<3;j++){
                  printf("a[%d][%d] = %d
      ",i,j,a[i][j]);
              }
          }
          
          return 0;
      }
      
    • 编译运行

      • 为什么 while 循环后面没有大括号也都运行 5 次:因为三条语句构成了逗号表达式,即为一个表达式:

        while(i < 5) printf("i = %d ",i),hello(),i++;

      • 数组变成了:{2,5,8,0,0,0,0,0,0}:因为数组 a[3][3] 的定义构成了逗号表达式,相当于 int a[3][3] = {2,5,8}; ,修改:int a[3][3] = {{0,1,2},{3,4,5},{6,7,8}}

      i = 0
      Hello
      i = 1
      Hello
      i = 2
      Hello
      i = 3
      Hello
      i = 4
      Hello
      a[0][0] = 2
      a[0][1] = 5
      a[0][2] = 8
      a[1][0] = 0
      a[1][1] = 0
      a[1][2] = 0
      a[2][0] = 0
      a[2][1] = 0
      a[2][2] = 0
      
  • 示例:一行代码实现 strlen

    • Demo

      #include <stdio.h>
      #include <assert.h>
      
      int strlen(const char* s)
      {
          //s+1是将指针指向下一个字符,strlen(s+1)+1是指长度=去掉当前字符的字符串的长度加1
          return assert(NULL) , (*s ? strlen( s + 1) + 1 : 0);
      }
          
      int main()
      {
          printf("len = %d
      ",strlen("ABCDEF"));
          printf("len = %d
      ",strlen(NULL));
          
          return 0;
      }
      
    • 编译运行

      len = 6
      test: test.c:7: strlen: Assertion `((void *)0)' failed.
      已放弃