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]( );