天天看點

C核心技術手冊(二十九)

4.2 非算術類型轉換

  指針和數組名,還有函數名也遵循隐式和顯式類型轉換,結構體和聯合體不能轉換,雖然它們的指導可以轉換為其他的指針類型。

4.2.1數組和函數操作訓示符

  一個數組或函數操作訓示符為具有類型的任何表達式,在大多數情況下,編譯器隐式地轉換一個數組的類型,及數組的名子轉為數組首元素的指針,數組表達式在以下情景下不能轉換為指針:

l  當使用sizeof操作符操作數組時;

l  當使用&操作符時;

l  當使用字元串變量初始化char或wchar_t數組時;

下面的例子示範了隐式轉換數組操作符為指針,使用%p列印指針值:

    #include <stdio.h>      
    int *iPtr = 0;                      // A pointer to int, initialized with 0.      
    int iArray[ ] = { 0, 10, 20 };       // An array of int, initialized.      
   int array_length = sizeof(iArray) / sizeof(int); // The number of elements:      
                                                     // in this case, 3.      
    printf("The array starts at the address %p./n", iArray);      
     *iArray = 5;                      // Equivalent to iArray[0] = 5;      
     iPtr = iArray + array_length - 1; // Point to the last element of iArray:      
                                      // Equivalent to      
                                      // iPtr = &iArray[array_length-1];      
 printf("The last element of the array is %d./n", *iPtr);      

在初始化array_length時,表達式sizeof(iArray)取得了數組的長度,而不是指針的大小,然而,在其他三個語句中,訓示符iArray隐式地轉換為一個指針,如下:

l  在第一次調用printf()時;

l  在使用操作符*時;

l  給iPtr指派時;

字元數組的名子在字元串操作中也當做指針使用,如下例:

    #include <stdio.h>      
    #include <string.h>            // Declares size_t strlen( const char *s )      
     char msg[80] = "I'm a string literal.";    // Initialize an array of char.      
    printf("The string is %d characters long./n", strlen(msg));      
                                               // Answer: 21.      
    printf("The array named msg is %d bytes long./n", sizeof(msg));      
                                               // Answer: 80.      

本例中strlen(msg)調用中,辨別符msg隐式地轉換為指向數組首元素的指針,類型為函數的入參類型const char *, strlen()僅僅統計字元開始到第一個null字元出現時所有的字元個數。

  類似地,任何表示函數的表達式,如函數名,也可以隐式地轉換為指向函數的指針,同樣,當使用位址操作符&時,将不會使用這種轉換,sizeof操作符不能使用在函數類型的操作中。下面的例子描述了函數名隐式轉換為指針,程式初始化了指向函數的指針,函數的調用在一個循環中。

    #include <stdio.h>      
    void func0( ) { puts("This is the function func0( ). "); }  // Two functions.      
    void func1( ) { puts("This is the function func1( ). "); }      
    /* ... */      
    void (*funcTable[2])(void) = { func0, func1 }; // Array of two pointers to      
                                                   // functions returning void.      
    for ( int i = 0; i < 2; ++i )   // Use the loop counter as the array index.      
       funcTable[i]( );