C和指针 第13章 高级指针话题 13.2 高级声明
13.2 高級聲明
?? ?高級的指針類型是如何聲明的。前面的章節介紹了表達式聲明的思路以及C語言的變量是如何通過推論進行聲明。還有第8章聲明指向數組的指針時已經看到過一些推論聲明的例子。現在通過觀察一系列越來越復雜的聲明進一步探索這個話題。
?? ?幾個簡單的例子如下:
?? ?int f; /*一個整型變量*/
?? ?int *f; /*一個指向整型的指針*/
?? ?第2個聲明是如何工作的:它把表達式*f聲明為一個整數。根據這個事實,肯定能推斷出f是個指向整型的指針。C聲明的這種解釋方法可以通過下面的聲明得到驗證:
?? ?int* f, g;
?? ?它并沒有聲明兩個指針。盡管它們之間存在空白,但星號還是作用于f的,只有f才是一個指針。g只是一個普通的整型變量。
?? ?int f();
?? ?f聲明為一個函數,它的返回值是一個整數。舊式風格的聲明對函數的參數并沒有提供任何信息。它只聲明f的返回值類型。現在將使用這種舊式風格,這樣例子看上去簡單一些,后面再回到完整的原型形式。
?? ?int *f();
?? ?要想推斷出它的含義,必須確定表達式*f()是如何進行求值的。首先執行的是函數調用操作符(),因為它的優先級高于間接訪問操作符。因此f是一個函數,它的返回值是一個指向整型的指針。
?? ?如果“推論聲明”看上去有點討厭,只要這樣考慮就可以了:用于聲明變量的表達式和普通的表達式在求值時所使用的規則相同。我們不需要為這類聲明學習一套單獨的語法。如果能夠對一個復雜表達式求值,同樣可以推斷出一個復雜聲明的含義,因為它們的原理是相同的。
?? ?接下來的一個聲明更為有趣:
?? ?int (*f)();
?? ?確定括號的含義是分析這個聲明的一個重要步驟。這個聲明有兩對括號,每對的含義各不相同。第2對括號是函數調用的操作符,但第1對括號只起到聚組的作用。它迫使間接訪問在函數調用之前進行,使f成為一個函數指針,它所指向的函數返回一個整型值。函數指針?是的,程序中的每個函數都位于內存中某個位置,所以存在指向那個位置的指針是完全可能的。
?? ?int *(*f)();
?? ?它和前一個聲明基本一樣,f也是一個函數指針,只是所指向的函數的返回是一個整型指針,必須對其進行間接訪問操作才能得到一個整型值。
?? ?把數組也考慮進去:
?? ?int f[];
?? ?這個聲明表示f是個整型數組。數組的長度暫時忽略,因為我們現在關心的是它的類型,而不是它的長度。
?? ?如果它們的鏈接屬性是external或者是作用于函數的參數,即使它們在聲明時未注明長度,也仍然是合法的。
?? ?int *f[];
?? ?這里出現了兩個操作符。下標的優先級更高,所以f是一個數組,它的元素類型是指向整型的指針。
?? ?下面這個例子隱藏著一個圈套。不管怎樣,讓我們先推斷出它的含義。
?? ?int f()[];
?? ?f是一個函數,它的返回值是一個整型數組。這里的圈套在于這個聲明是非法的---函數只能返回標量值,不能返回數組。
?? ?這里還有一個例子,頗費思量。
?? ?int f[]();
?? ?現在,f似乎是一個數組,它的元素類型是返回值為整型的函數。這個聲明也是非法的,因為數組元素必須具有相同的長度,但不同的函數顯然具有不同的長度。
?? ?但是,下面這個聲明是合法的:
?? ?int (*f[])();
?? ?首先,必須找到所有的操作符,然后按照正確的次序執行它們。同樣,這里有兩對括號,它們分別具有不同的含義。括號內的表達式*[]首先進行求值。所以f是一個元素為某種類型的指針的數組。表達式末尾的()是函數調用操作符,所以f肯定是一個數組,數組元素的類型是函數指針,它所指向的函數的返回值是一個整型值。
?? ?如果大家搞清楚了上面最后一個聲明,下面這個應該是比較容易的了:
?? ?int *(*f[])();
?? ?它和上面那個聲明的唯一區別就是多了一個間接訪問操作符,所以這個聲明創建了一個指針數組,指針所指向的類型是返回值為整型指針的函數。
?? ?到目前為止,這里使用的是舊式風格的聲明,目的是為了讓例子更簡單一些。但是ANSI C要求我們使用完整的函數原型,使聲明更為明確。例如:
?? ?int (*f)( int, float );
?? ?int *(*g[])( int, float );
?? ?前者把f聲明為一個函數指針,它所指的函數接受兩個參數,分別是一個整型值和浮點型值,并返回一個整型值。后者把g聲明為一個數組,數組的形式是一個函數指針,它所指向的函數接受兩個參數,分別是一個整型值和浮點型值,并返回一個整型指針。盡管原型增加了聲明的復雜程度,但我們還是應該提倡這種風格,因為它向編譯器提供了一些額外的信息。
?? ?提示:
?? ?如果大家使用的是UNIX系統,并能訪問Internet,則可能獲得一個名叫cdecl的程序,它可以在C語言的聲明和英語之間進行轉換。它可以解釋一個現存的C語言聲明:
?? ?? ?int (*(*f)())[10]; /* f as pointer to function returning pointer to array 10 of int. */
?? ?或者給出一個聲明的語法:
?? ?/* x as pointer to array to array 10 of pointer to function returning int. */
?? ?int (*(*x)[10])();?
?? ?cdecl的源代碼可以從comp.sources.unix.newsgroup存檔文件第14卷中獲得。 (真的有源碼呢!感興趣自己可以去看看呢。)
?? ?/*
?? ?** 高級聲明。
?? ?** advanced_declaration_code_2.c
?? ?*/
?? ?#include <stdio.h>
?? ?#include <stdlib.h>
?? ?int f4();
?? ?int f5();
?? ?/* can't pass compilation:
?? ?** because of [Error] 'f10' declared as function returning an array
?? ?** int f10()[10]; /* In terms of priority, f10 should be a function, the return value of function is an
?? ?** array, but it is?illegal actually, because c standard stipulates the function can't return an array. */
?? ?/* can't pass compilation:
?? ?** because of [Error] declaration of 'f11' as array of functions
?? ?** int f11[10](); /* In terms of priority, f11 should be an array, the return value of array is?
?? ?**afunction, but it is also illegal actually, because every element in array must have the same?
?? ?** length, but different function may have?different length obviously, becuase the function only
?? ?** provide the return type of function before ANSI C standard.*/
?? ?int (*f12[10])(); /* f12 is an array, every element in array is a pointer points to a function, the return value of function is an int. */
?? ?int *(*f13[10])(); /* f13 is an array, every element in array is a pointer points to a function, the return value of?function is a pointer points to an int. */
?? ?/* ANSI C requests we must use function prototype. */
?? ?int (*f14)( int, float ); /* f14 is a pointer points to a function, this function receives two parameters, one is an int, the other is a float, the return value of function is an int. */
?? ?int *(*g2[10])( int, float ); /* g2 is an array, every element in array is a pointer points to a function, this function receives two parameter, one is an int, the other is a float, this return value of function is a pointer points to an int. */
?? ?int (*(*f15)())[10]; /* f15 as pointer to function returning pointer to array 10 of int. */
?? ?
?? ?int main( void ){
?? ??? ?int f; /* an integral variable */
?? ??? ?int *f2; /* a pointer points to an int */
?? ??? ?int *f3, g; /* f3 is a pointer points to an int, g is an int */
?? ??? ?printf( "sizeof(int) = %zd, sizeof(int *) = %zd\n", sizeof(int), sizeof(int *) );
?? ??? ?printf( "sizeof(f) = %zd, sizeof(f2) = %zd, sizeof(f3) = %zd, sizeof(g) = %zd\n",
?? ??? ?sizeof(f), sizeof(f2), sizeof(f3), sizeof(g) );
?? ??? ?int f4(); /*f4 is a function name, the return value of function is an int. */
?? ??? ?int f5(); /*f5 is a function name, the return value of function is an int. */
?? ??? ?int (*f6)(); /* f6 is a pointer points to a function, the return value of function is an int */
?? ??? ?int *(*f7)(); /* f7 is a pointer points to a function, the return value of function is a pointer points to an int */
?? ??? ?printf( "sizeof(f4) = %zd, sizeof(f5) = %zd, sizeof(f6) = %zd, sizeof(f7) = %zd\n",
?? ??? ?sizeof(f4), sizeof(f5), sizeof(f6), sizeof(f7) );
?? ??? ?int f8[10]; /* f8 is an integral array. */
?? ??? ?int *f9[10]; /* the priority of [] operator is higher than the * operator, so executes [] operation firstly. f9 is an array, every element in array is an int * */
?? ??? ?printf( "sizeof(f8) = %zd, sizeof(f9) = %zd\n", sizeof(f8), sizeof(f9) );
?? ??? ?int (*(*x)[10])(); /* x as pointer to array to array 10 of pointer to function returning int. */
?? ??? ?printf( "sizeof(x) = %zd, sizeof(f12) = %zd, sizeof(f13) = %zd, sizeof(f14) = %zd\n",
?? ??? ?sizeof(x), sizeof(f12), sizeof(f13), sizeof(f14) );
?? ??? ?printf( "sizeof(g2) = %zd, sizeof(f15) = %zd\n", sizeof(g2), sizeof(f15) );
?? ??? ?
?? ??? ?return EXIT_SUCCESS;
?? ?}
?? ?
?? ?int f4( a, b )
?? ?long a, b;{
?? ??? ?return (int)a;
?? ?}
?? ?int f5(a, b, c)
?? ?int a, b, c;{
?? ??? ?return b;
?? ?}
/* 輸出:*//* ISO C99標準 */?
?? ?/*
?? ?** 高級聲明。
?? ?** advanced_declaration_code.cpp
?? ?*/
?? ?#include <stdio.h>
?? ?#include <stdlib.h>
?? ?int f4( void ){
?? ??? ?int a;
?? ??? ?int b;
?? ??? ?return a;
?? ?}
?? ?int f5( void ){
?? ??? ?int a;
?? ??? ?int b;
?? ??? ?int c;
?? ??? ?int d;
?? ??? ?return a;
?? ?}
?? ?/* can't pass compilation:
?? ?** because of [Error] declaration of 'f10' as function returning an array.
?? ?** int f10()[10]; ?? ?/* In terms of priority, f10 should be a function, the return value of function is an
?? ?** array, but it is illegal actually, because c standard stipulates the function can't return an array.
?? ?*/?? ?
?? ?int main( void ){
?? ??? ?int f; /* an integral variable */
?? ??? ?int *f2; /* a pointer points to an int */
?? ??? ?int *f3, g; /* f3 is a pointer points to an int, g is an int */
?? ??? ?printf( "sizeof(int) = %zd, sizeof(int *) = %zd\n", sizeof(int), sizeof(int *) );
?? ??? ?printf( "sizeof(f) = %zd, sizeof(f2) = %zd, sizeof(f3) = %zd, sizeof(g) = %zd\n",
?? ??? ?sizeof(f), sizeof(f2), sizeof(f3), sizeof(g) );
?? ??? ?int f4(); /*f4 is a function name, the return value of function is an int. */
?? ??? ?int f5(); /*f5 is a function name, the return value of function is an int. */
?? ??? ?int (*f6)(); /* f6 is a pointer points to a function, the return value of function is an int */
?? ??? ?int *(*f7)(); /* f7 is a pointer points to a function, the return value of function is a pointer points to an int */
?? ??? ?/* can't pass compilation:
?? ??? ?** because of [Error] ISO C++ forbids applying 'sizeof' to an expression of function type[-
?? ??? ?** fpermissive]
?? ??? ?** printf( "sizeof(f4) = %zd, sizeof(f5) = %zd\n", sizeof(f4), sizeof(f5) );
?? ??? ?*/
?? ??? ?printf( "sizeof(f6) = %zd, sizeof(f7) = %zd\n", sizeof(f6), sizeof(f7) );
?? ??? ?int f8[10]; /* f8 is an integral array. */
?? ??? ?int *f9[10]; /* the priority of [] operator is higher than the * operator, so executes [] operation firstly. f9 is an array, every element in array is an int */
?? ??? ?printf( "sizeof(f8) = %zd, sizeof(f9) = %zd\n", sizeof(f8), sizeof(f9) );
?? ??? ?/* can't pass compilation:
?? ??? ?** because of [Error] declaration of 'f11' as array of functions
?? ??? ?** int f11[10](); /* In terms of priority, f11 should be an array, the return value of array is a function, but it is also illegal actually.
?? ??? ?*/
?? ??? ?int (*f12[10])(); /* f12 is an array, every element in array is a pointer points to a function, the return value of function is an int. */
?? ??? ?int *(*f13[10])(); /* f13 is an array, every element in array is a pointer points to a function, the return value of?function is a pointer points to an int. */
?? ??? ?/* ANSI C requests we must use function prototype. */
?? ??? ?int (*f14)( int, float ); /* f14 is a pointer points to a function, this function receives two parameters, one is an int, the other is a float, the return value of function is an int. */
?? ??? ?int *(*g2[10])( int, float ); /* g2 is an array, every element in array is a pointer points to a function, this function receives two parameter, one is an int, the other is a float, this return value of function is a pointer points to an int. */
?? ??? ?printf( "sizeof(f14) = %zd, sizeof(g2) = %zd\n", sizeof(f14), sizeof(g2) );
?? ??? ?int (*(*f15)())[10]; /* f as pointer to function returning pointer to array 10 of int. */
?? ??? ?int (*(*x)[10])(); /* x as pointer to array to array 10 of pointer to function returning int. */
?? ??? ?printf( "sizeof(f15) = %zd, sizeof(x) = %zd\n", sizeof(f15), sizeof(x) );
?? ??? ?
?? ??? ?return EXIT_SUCCESS;
?? ?}
/* 輸出:*//* ISO C++11 標準 */
總結
以上是生活随笔為你收集整理的C和指针 第13章 高级指针话题 13.2 高级声明的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: DSA_常用10种算法(java数据结构
- 下一篇: dcs world f15c教学_高端D