1、左值和右值
表達(dá)式的左值是它的地址,右值是該地址所存儲(chǔ)的內(nèi)容。比如下面代碼:
x = x + 1;
這兩個(gè) x 有什么不同呢?第一個(gè)表達(dá)式 x 表示的是它的左值,而第二個(gè)表達(dá)式 x 表示的是它的右值。一個(gè)表達(dá)式能不能放到 賦值操作符 的左邊,取決于這個(gè)表達(dá)式有沒(méi)有左值,同樣的,一個(gè)表達(dá)式能不能放到 賦值操作符 的右邊,取決于它有沒(méi)有右值。
一個(gè)表達(dá)式究竟是取左值還是右值,需要結(jié)合上下文,大多數(shù)表達(dá)式同時(shí)具有左值和右值。
2、指針類型、數(shù)組類型和函數(shù)類型
C++是一種強(qiáng)類型語(yǔ)言,類型在程序中的非常重要,每個(gè)變量和表達(dá)式都有一個(gè)確定的類型,類型匹配和類型轉(zhuǎn)換也是C++語(yǔ)言中的重要部分。除了內(nèi)建的一些類型和用戶自定義類型(包括類類型),下面重點(diǎn)說(shuō)一下指針類型、數(shù)組類型和函數(shù)類型。
T* a;
聲明一個(gè)變量a,它的類型是T*(指向類型T的指針類型)。
T arr[100];
聲明一個(gè)變量arr,它的類型是 T[100](一維,維長(zhǎng)100,元素類型為T的數(shù)組)。
T f(void){/* . . . */}
聲明一個(gè)變量f,它的類型是 T(void)(返回值為T,參數(shù)為void的函數(shù))
特別要強(qiáng)調(diào)的是,arr 的類型和 f 的類型都不是指針。這兩個(gè)類型的表達(dá)式?jīng)]有右值。
3、&、* 操作符
* 操作符應(yīng)用與左值表達(dá)式,以表達(dá)式左值為地址,取出表達(dá)式類型的值,作為右值返回。
& 操作符應(yīng)用于左值表達(dá)式,返回表達(dá)式的左值。
注意*、& 操作符的操作數(shù)必須擁有左值。
4、左值到右值的轉(zhuǎn)換
C++ 標(biāo)準(zhǔn)轉(zhuǎn)換包含 左值到右值的轉(zhuǎn)換。因?yàn)閿?shù)組類型和函數(shù)類型的表達(dá)式?jīng)]有右值,所以特別這里要說(shuō)明數(shù)組類型和函數(shù)類型到右值的轉(zhuǎn)換。比如上文所說(shuō) arr ,當(dāng)它作為賦值操作符的操作數(shù)時(shí),它需要轉(zhuǎn)換為 T* 類型的指針(注意類型是指針!!),其值等于第一個(gè)元素的地址。而上文中所說(shuō)的 f,當(dāng)它作為賦值操作符的操作數(shù)時(shí),它需要轉(zhuǎn)換為 T(*)(void) 的指針(注意類型是指針!!),它指向f的地址。
5、對(duì)數(shù)組類型或者函數(shù)類型施加&、*操作符
&arr、 *arr、 &f、 *f 這些表達(dá)式都是什么呢?打開RTTI,在VC里運(yùn)行下面代碼:
1 #include "stdafx.h"
2 #include <iostream>
3 using namespace std;
4
5 int func()
6 {
7 int i = 2;
8 return i;
9 }
10
11 int _tmain(int argc, _TCHAR* argv[])
12 {
13 int arr[100] = {0,1,2,3};
14
15 cout<<typeid(func).name()<<endl;
16 cout<<typeid(*func).name()<<endl;
17 cout<<typeid(&func).name()<<endl;
18 cout<<endl;
19 cout<<typeid(arr).name()<<endl;
20 cout<<typeid(*arr).name()<<endl;
21 cout<<typeid(&arr).name()<<endl;
22 cout<<typeid(int*).name()<<endl;
23
24 getchar();
25 return 0;
26 }
運(yùn)行結(jié)果如下:
int __cdecl(void)
int __cdecl(void)
int (__cdecl*)(void)
int [100]
int
int (*)[100]
int *
可以看出 *func 和 func 類型相同,是函數(shù)類型,而&func 是指向函數(shù)的指針。arr 是數(shù)組類型,*arr 是 T 類型, &arr 是 指向數(shù)組的指針(這個(gè)比較費(fèi)解)
因?yàn)?func 和 func 是等價(jià)的,所以可以這樣調(diào)用 func:
(***********************func)();
如果要用 &func,必須這樣(注意第一個(gè)一定是 *):
(*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&func)();
至于 arr、*arr、&arr 因?yàn)轭愋筒煌豢苫煊茫?dāng)然用來(lái) memset 的話,表達(dá)式 arr 和 &arr 的值都為第一個(gè)元素的地址,最終都被轉(zhuǎn)換為 void* 。