C

閱讀 C 語言規格書的重要性之序章 : 一元運算元的案例分析

案例一

引述 C 語言規格書中的三點來解釋為何以下程式碼能正常運作

int main() {
   return (********puts)("Hello");
}

[1] 6.5.3.2-4 The unary * operator denotes indirection. If the operand pointers to a function, the result is a function designator;

[2] 6.3.2.1-4 A function designator is an expression that has function type.

[3] * is Right associative operator

由於 puts 的 function signature 是 int puts(const char *s),所以, 每一次經過 * operator 的運算後得到的結果是仍然是 int. 因此, * 的數目不會影響結果。最後 return 的值是根據 s 的長度加上 ‘\n’。而這個例子 return 給 entry point 的值是 6.


案例二

以下的表達式 [a] 和 [b] 是否等價?

[a] (**printf)("...");
[b] (&printf)("...");

引述 C語言規格書:

[0] 6.3.2.1-4 A function designator is an expression that has function type.
[1] 6.5.3.2-1 The operand of the unary &; operator shall be a function designator
[2] 6.5.3.2-3 The unary &; operator yields the address of its operand.
[3] 6.5.3.2-4 The unary * operator denotes indirection. If the operand points to a function, the result is a function designator.

假設 printf 的 function signature 是 int printf (const char *, …);
那麼每一次經過 * operator 和 & operator 的運算後得到的結果是仍然是 int ,所以這兩個 expression 是等價的

[a] (**printf)(“..") -> (* int printf)(“..") -> (int printf)(“..")
[b] (&printf)(“…"); -> int printf (“…");

如果把 (&printf)(“…"); 變成 (&&printf)(“…"); 那麼出現以下 Error Message:

error: called object is not a function or function pointer

原因是, 第一次的 & operator 的運算後得到的結果是 int; 第二次進行 & operator 的時候, semantics 是 address of operand, 而 operand 就是 int. 所以就會出現 Error.


案例三和四是以上的變化,其原理是一樣的。


案例三

double mm = 111.17;

double* get_money (double m) {
    mm = m;
    return &mm; 
}

int main() {
    double* m1 = (&get_money)(3.7117718);
    printf("%d\n", (&printf)("%.3lf\n", *m1));

    double* m2 = (*&*&get_money)(7.3881171);
    printf("%d\n", (&printf)("%.5lf\n", *m2));

    return 0;
}

/*
 * gcc -w -std=c99 -o main main.c && ./main 
 * 3.712
 * 6
 * 7.38812
 * 8
 */


案例四

 struct bank {
    double money;
    float rate;
};

char* ary = {'A', 'B', 'C'};

char* get_char(void) {
    return ary + 1;
}

struct bank* get_bank(struct bank *b) {                                                 
    b->money = 11973.711;
    b->rate = 817.3;
    return b;
}

double get_money (double m) {
    return m;  
}

int main() {
    struct bank* btw = (struct bank *) malloc (sizeof (struct bank));
    btw->money = 117.37911;
    btw->rate = 3.718;

    struct bank* bmo = (***************************get_bank)(btw);

    printf("%d\n",  (****puts)("Hello"));
    printf("%lf\n", (******************get_money)(bmo->money));                         
    printf("%c\n",  (***************************************************************************************************************************************************************************************************************************************************************************get_char)());
    
    return (**************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************puts)("Hello World!!");                  
}

/*
gcc -g -w -std=c99 -o main main.c
./main 
Hello
6
11973.711000
B
Hello World!!
*/

-完-

廣告

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

您的留言將使用 WordPress.com 帳號。 登出 / 變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 / 變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 / 變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 / 變更 )

連結到 %s