【C進階】18、三目運算子和逗號表示式

bryson發表於2021-11-02

Summary

1)在C語言中,三目運算子返回的結果是一個右值,並不是一個變數(不能放在賦值符號左側)

2)三目運算子的返回型別

  • 通過隱式型別轉換規則返回b和c中的較高型別(注意:char和short在運算時會隱式轉換成int)
  • 當b和c不能隱式轉換到同一型別時編譯出錯

3)逗號表示式(exp1, exp2, ... expN)

  • 逗號表示式用於將多個子表示式連線為一個表示式
  • 逗號表示式的值為最後一個子表示式的值(前N-1個子表示式可以沒有返回值)
  • 計算順序為從左到右

4)一般一行程式碼實現某種功能時,往往需要用到遞迴 + 逗號表示式 + 三目運算子

三目運算子和逗號表示式

1、三目運算子

三目運算子(expression ? a : b):當expression的值為真時,返回a的值;否則返回b的值

  • 程式碼閱讀

    int a = 1;
    int b = 2;
    int c = 0;
    
    c = a < b ? a : b;      // c = 1 
    (a < b ? a : b) = 3;    // error, lvalue required as left operand of assignment

三目運算子(expression ? a : b)的返回型別:

  • 通過隱式型別轉換規則返回b和c中的較高型別
  • 當b和c不能隱式轉換到同一型別時編譯出錯

    char c = 0;
    short s = 0;
    int i = 0;
    double d = 0;
    char* p = "str";
    
    printf("%d\n", sizeof(c ? c : s));    // 4, 返回型別隱式轉換為int
    printf("%d\n", sizeof(i ? i : d));    // 8,返回型別隱式轉換為double
    printf("%d\n", sizeof(d ? d : p));    // error,double和char*不能隱式型別轉換為同一型別

2、逗號表示式

逗號表示式(exp1, exp2, ... expN)

  • 逗號表示式用於將多個子表示式連線為一個表示式
  • 逗號表示式的值為最後一個子表示式的值(前N-1個子表示式可以沒有返回值)
  • 計算順序為從左到右

    // 以下程式碼會輸出什麼?
    int i = 0;
    
    while (i < 5)
      printf("i = %d\n", i),
    
    i++;
    
    // 分析,這段程式碼並不會編譯失敗,也不會死迴圈,因為這是一個逗號表示式
    int i = 0;
    
    while(i < 5)
      printf("i = %d\n", i), i++;
  • // 以下程式碼會輸出什麼?
    int a[3][3] = {
      (0, 1, 2),
      (3, 4, 5),
      (6, 7, 8)
    }; 
    
    int i=0, j=0;
    for(i = 0; i<3; i++)
    {
      for(j = 0; j<3; j++)
      {
          printf("a[%d][%d] = %d\n", i, j, a[i][j]);
      }
    }
    
    // 分析
    這段程式碼並不會像乍看一樣輸出 0 ~ 8,而輸出的是2, 5, 8, 0, 0, ...
    原因在於逗號表示式。初始化時使用的是逗號表示式,而不是花括號{}
    相當於:
    int a[3][3] = {2, 5, 8};

3、一行程式碼實現strlen

遞迴 + 三目運算子 + 逗號表示式

  • 版本一,未考慮空指標,入參為NULL時會崩潰

    int myStrlen(const char* s)
    {
      return (*s ? myStrlen(s+1)+1 : 0);
    }
  • 版本二,考慮空指標,使用巢狀的三目運算子

    int myStrlen(const char* s)
    {
      return (s == NULL ? -1 : *s ? myStrlen(s+1)+1 : 0);
    }
  • 版本三,使用assert斷言,逗號表示式 + 三目運算子

    int myStrlen(const char* s)
    {
      return (assert(s), *s ? myStrlen(s+1)+1 : 0);
    }

本文總結自“狄泰軟體學院”唐佐林老師《C語言進階課程》。
如有錯漏之處,懇請指正。

相關文章