數(shù)據(jù)類型
c++程序員已經(jīng)知道c語(yǔ)言有五種數(shù)據(jù)類型:void,int,float,double和char:
類型 描述
void 無(wú)數(shù)據(jù)類型
int 整數(shù)類型
float 浮點(diǎn)數(shù)
double 雙精度浮點(diǎn)數(shù)
char 字符型
c++有額外定義了兩種類型:bool和wchar_t:
類型 描述
bool 布爾變量,true或者false
wchar_t 寬字符
類型修飾符
這幾個(gè)類型中的部分可以使用以下幾個(gè)關(guān)鍵字來修飾:signed,unsigned,short和long. 如果只有類型修飾符自己被使用,則數(shù)據(jù)類型會(huì)被缺省地認(rèn)為int.下面是一個(gè)完整的列表列出了可能的數(shù)據(jù)類型(等效的會(huì)被顯示在同一行,并且用,隔開)
整數(shù)類型
bool
char, signed char
unsigned char
short, short int, signed short int
unsigned short, unsigned short int
int, signed int
unsigned, unsigned int
long, long int, signed long, signed long int
unsigned long, unsigned long int
浮點(diǎn)類型
float
double
long double
可選支持的整數(shù)類型
long long, signed long long, long long int, signed long long int
unsigned long long, unsigned long long int
wchar_t
類型的大小和范圍
任何一種數(shù)據(jù)類型的大小和范圍都是編譯器相關(guān)的. 頭文件"cfloat"(或者"float.h")經(jīng)常定義了各種數(shù)據(jù)類型的最小值.你可以使用操作符sizeof來測(cè)試任何一種數(shù)據(jù)類型的大小(這里的大小是指該類型的變量說占用的空間大小,即占用的字節(jié)數(shù)).然而,很多的系統(tǒng)會(huì)依據(jù)某一標(biāo)準(zhǔn)來實(shí)現(xiàn)數(shù)據(jù)類型.整型和浮點(diǎn)型通常是32位,字符8位,雙精度64位.布爾變量則常會(huì)是8位.long long類型是64位.
數(shù)字值的限制是定義在頭文件里. 模板化的類numeric_limits提供了系統(tǒng)相關(guān)的c++數(shù)據(jù)類型的表現(xiàn)。 使用適當(dāng)?shù)暮瘮?shù)并且以數(shù)據(jù)類型作為模板參數(shù)可以返回一些需要的信息。需要注意的是mumeric_limits是可以被用戶定義的類型重載。
下面是一些相關(guān)的函數(shù)(譯者:其實(shí)有些是靜態(tài)成員變量,至少在dev-c++里如此):
方法 返回類型 描述
is_specialized bool
radix int 指數(shù)的底
digits int 尾數(shù)中的基數(shù)位數(shù)
digits10 int 尾數(shù)中的10進(jìn)制數(shù)位數(shù)
is_signed bool
is_integer bool
is_exact bool
min 可以表示的最小數(shù)(不是負(fù)的最小數(shù))
max 數(shù)
epsilon 固有誤差
round_error 取正誤差(即四舍五入就是0.5)
infinity
quiet_NaN 不能標(biāo)示浮點(diǎn)錯(cuò)誤的無(wú)效數(shù)字
signaling_NaN 標(biāo)示浮點(diǎn)錯(cuò)誤的無(wú)效數(shù)字
denorm_min
min_exponent int
min_exponent10 int
max_exponent int
max_exponent10 int
has_infinity bool
has_quiet_NaN bool
has_signaling_NaN bool
has_denorm_denorm_style
has_denorm_loss bool
is_iec559 bool 遵照IEC-559規(guī)范
is_bounded bool
is_modulo bool
traps bool
tinyness_before bool
round_style float_round_style { round_to_nearest, … } //float_round_style是一個(gè)枚舉類型,具體可以參考
最通常的用法就是邊界檢查來確認(rèn)某一數(shù)據(jù)類型可以表示的最小值。接下來的代碼打印出了該系統(tǒng)平臺(tái)上short類型的最值:
#include
std::cout << "Maximum short value: " << std::numeric_limits::max() << std::endl;
std::cout << "Minimum short value: " << std::numeric_limits::min() << std::endl; 理解類型聲明
簡(jiǎn)單的類型聲明很容易理解:
int i
然而,有時(shí)也會(huì)有十分復(fù)雜的類型聲明:
double **d[8] //hmm...
char *(*(**foo [][8])())[] //augh! foo到底是什么?
為了理解上面的聲明,可以遵循下面的三個(gè)規(guī)則:
1.從變量名開始(在上例中就是d或者foo)
2.以數(shù)據(jù)類型結(jié)尾(double或者char)
3.如果可以的話向右,必須的話則向左(括號(hào)可能會(huì)讓你改變方向)
例如:
表達(dá)式 意義
double **d[8];
double **d[8]; d 是 … double
double **d[8]; d 是 8維數(shù)組 … double
double **d[8]; d 是 8維數(shù)組且成員為 指針且指向 … double
double **d[8]; d 是 8維數(shù)組且成員為 指針且指向 指針且指向 double
另外一個(gè)例子:
表達(dá)式 意義
char *(*(**foo [][8])())[]
char *(*(**foo [][8])())[] foo 是 … char
char *(*(**foo [][8])())[] foo 是 一個(gè)數(shù)組 … char
char *(*(**foo [][8])())[] foo 是 一個(gè)數(shù)組且成員為 8維數(shù)組 … char
char *(*(**foo [][8])())[] foo 是 一個(gè)數(shù)組且成員為 8維數(shù)組且成員為 指針且指向 … char
char *(*(**foo [][8])())[] foo 是 一個(gè)數(shù)組且成員為 8維數(shù)組且成員為 指針且指向 指針且指向 … char
char *(*(**foo [][8])())[] foo 是 一個(gè)數(shù)組且成員為 8維數(shù)組且成員為 指針且指向 指針且指向 函數(shù)且返回 … char
char *(*(**foo [][8])())[] foo 是 一個(gè)數(shù)組且成員為 8維數(shù)組且成員為 指針且指向 指針且指向 函數(shù)且返回 指針且指向 … char
char *(*(**foo [][8])())[] foo 是 一個(gè)數(shù)組且成員為 8維數(shù)組且成員為 指針且指向 指針且指向 函數(shù)且返回 指針且指向 數(shù)組 … char
char *(*(**foo [][8])())[] foo 是 一個(gè)數(shù)組且成員為 8維數(shù)組且成員為 指針且指向 指針且指向 函數(shù)且返回 指針且指向 數(shù)組且成員為 指針且指向 char
譯注:
我們也可以采用另外一種方法就是層層類型定義的方法來解讀,不過是從外向內(nèi)的.比如例子1:
typedef double * pDouble;
typedef pDouble* ppDouble;
typedef ppDouble a8ppDouble[8];
a8ppDouble d;
第二個(gè)例子:
typedef char * pchar;
typedef pchar apchar[];
typedef apchar * papchar;
typedef papchar fpapchar();
typedef papchar (*pfpapchar)();
typedef pfpapchar * ppfpapchar;
typedef ppfpapchar a8ppfpapchar[8];
typedef a8ppfpapchar aa8ppfpapchar[];
typedef aa8ppfpapchar foo;
附文:
下面是對(duì)Steve Friedl的參考文章的部分譯文,因?yàn)檫@里也同樣的是解說這兩個(gè)例子,不過對(duì)于規(guī)則上述說更詳細(xì)。
基本和派生類型
基本類型就是上邊提到的那些基本類型,這里還包括了struct,enum和union(譯注:因?yàn)檫@個(gè)說明是針對(duì)c語(yǔ)言的,所以對(duì)于c++來說還要加上一個(gè)class類型)
一個(gè)聲明只能定義一種基本類型,并且它總是出現(xiàn)在聲明式的最左邊?;绢愋涂梢员慌缮愋蛿U(kuò)張或者說是修飾,并且c有三種派生類型:
* 指針且指向(pointer to...)
這里*表明這是一個(gè)指針,而且不言自明地它要指向某個(gè)東西
[] 數(shù)組且成員為(array of...)
數(shù)組可以是已定維數(shù)的--[10]--也可以是未定維數(shù)的--[],但是維數(shù)在我們理解聲明具體含義的時(shí)候不是那么重要。典型地我們會(huì)把維數(shù)包含在聲明里。這樣可以明了的說“數(shù)組且成員為”某些東西。
() 函數(shù)且返回(function returning...)
函數(shù)通常是由一對(duì)圓括號(hào)來表明的--盡管可能在里面發(fā)現(xiàn)參數(shù)類型。參數(shù)列表其實(shí)在我們理解聲明的時(shí)候是不重要的,可以忽略。應(yīng)該注意到的是函數(shù)的括號(hào)和分組改變優(yōu)先級(jí)的括號(hào)是不一樣的:分組括號(hào)總是包圍變量而函數(shù)括號(hào)卻總是在變量名(即函數(shù)名)的右邊。
如果函數(shù)不返回值則它是無(wú)意義的(我們可以使用void來表示返回為空)。
一個(gè)派生類型總是修飾一個(gè)基本變量或者另外一個(gè)派生變量。我們?cè)诶斫饴暶鞯臅r(shí)候一定要包括介詞(to,of,returning)。說“指針”而不是“指針且指向...”會(huì)導(dǎo)致你的聲明分離。
操作符的優(yōu)先級(jí)
幾乎每一個(gè)c程序員都很熟悉操作符的優(yōu)先級(jí)表。比如乘除的優(yōu)先級(jí)要高于加減,但是括號(hào)可以改變這個(gè)優(yōu)先級(jí)。這個(gè)對(duì)于通常的表達(dá)式很自然,但是這個(gè)規(guī)則也可以運(yùn)用到聲明語(yǔ)句中--它們是類型表達(dá)式而不是計(jì)算表達(dá)式。
數(shù)組符號(hào)[]和函數(shù)符號(hào)()比指針*有更高的優(yōu)先級(jí),這樣我們可以推導(dǎo)出一些規(guī)則(這個(gè)規(guī)則和上邊所提的是一樣的,這里不再啰嗦,離子的推衍也不再重復(fù))。
抽象聲明
C標(biāo)準(zhǔn)也支持抽象聲明。它可以用在需要類型描述但是又不需要實(shí)際變量的情況下--cast,拋擲,和作為sizeof的參數(shù)。比如:
int (*(*)())()
對(duì)于上邊的問題--從哪里開始,答案是找到一個(gè)變量名可以放得下的地方,然后把它當(dāng)成一個(gè)通常的聲明。只有一個(gè)地方可以放置這個(gè)變量名并且找到它也是直截了當(dāng)?shù)?。遵循以下語(yǔ)法規(guī)則:
- 在*的右邊
- 在[]的左邊
- 在函數(shù)操作符()的左邊
- 在分組括號(hào)()的內(nèi)部
由上面的例子我們可以看到有兩個(gè)地方符合前三條規(guī)則:
int (*(* • ) • ())()
但是如果考慮則四條,則只有左邊的位置符合了。
int (*(*foo)())()
它表示:
foo是 指針且指向 函數(shù)且返回 指針且指向 函數(shù)且返回 int
語(yǔ)義限制
注意不是所有的派生組合都被允許的.這樣就可能聲明一個(gè)合乎語(yǔ)法卻沒有語(yǔ)義內(nèi)涵的東西來:
--不能有 數(shù)組且成員為函數(shù)
使用 數(shù)組且成員為 指針且指向 函數(shù)且返回.... (譯注:但是我們知道函數(shù)的地址就是函數(shù)本身,所以可以說 數(shù)組且成員為 函數(shù)指針且返回)
--函數(shù)不能返回函數(shù)
同樣使用函數(shù)指針代替
--函數(shù)不能返回?cái)?shù)組
可以使用 函數(shù)且返回 指針且指向 數(shù)組且成員為...(譯注:同樣地我們知道數(shù)組名同時(shí)也是數(shù)組首元素的地址,還是該數(shù)組的地址)
--數(shù)組中只有最左的[]可以是未定義的
--void是限制類型,它只有在和指針*以及函數(shù)()在一起時(shí)才有效.
c++程序員已經(jīng)知道c語(yǔ)言有五種數(shù)據(jù)類型:void,int,float,double和char:
類型 描述
void 無(wú)數(shù)據(jù)類型
int 整數(shù)類型
float 浮點(diǎn)數(shù)
double 雙精度浮點(diǎn)數(shù)
char 字符型
c++有額外定義了兩種類型:bool和wchar_t:
類型 描述
bool 布爾變量,true或者false
wchar_t 寬字符
類型修飾符
這幾個(gè)類型中的部分可以使用以下幾個(gè)關(guān)鍵字來修飾:signed,unsigned,short和long. 如果只有類型修飾符自己被使用,則數(shù)據(jù)類型會(huì)被缺省地認(rèn)為int.下面是一個(gè)完整的列表列出了可能的數(shù)據(jù)類型(等效的會(huì)被顯示在同一行,并且用,隔開)
整數(shù)類型
bool
char, signed char
unsigned char
short, short int, signed short int
unsigned short, unsigned short int
int, signed int
unsigned, unsigned int
long, long int, signed long, signed long int
unsigned long, unsigned long int
浮點(diǎn)類型
float
double
long double
可選支持的整數(shù)類型
long long, signed long long, long long int, signed long long int
unsigned long long, unsigned long long int
wchar_t
類型的大小和范圍
任何一種數(shù)據(jù)類型的大小和范圍都是編譯器相關(guān)的. 頭文件"cfloat"(或者"float.h")經(jīng)常定義了各種數(shù)據(jù)類型的最小值.你可以使用操作符sizeof來測(cè)試任何一種數(shù)據(jù)類型的大小(這里的大小是指該類型的變量說占用的空間大小,即占用的字節(jié)數(shù)).然而,很多的系統(tǒng)會(huì)依據(jù)某一標(biāo)準(zhǔn)來實(shí)現(xiàn)數(shù)據(jù)類型.整型和浮點(diǎn)型通常是32位,字符8位,雙精度64位.布爾變量則常會(huì)是8位.long long類型是64位.
數(shù)字值的限制是定義在頭文件
下面是一些相關(guān)的函數(shù)(譯者:其實(shí)有些是靜態(tài)成員變量,至少在dev-c++里如此):
方法 返回類型 描述
is_specialized bool
radix int 指數(shù)的底
digits int 尾數(shù)中的基數(shù)位數(shù)
digits10 int 尾數(shù)中的10進(jìn)制數(shù)位數(shù)
is_signed bool
is_integer bool
is_exact bool
min
max
epsilon
round_error
infinity
quiet_NaN
signaling_NaN
denorm_min
min_exponent int
min_exponent10 int
max_exponent int
max_exponent10 int
has_infinity bool
has_quiet_NaN bool
has_signaling_NaN bool
has_denorm
has_denorm_loss bool
is_iec559 bool 遵照IEC-559規(guī)范
is_bounded bool
is_modulo bool
traps bool
tinyness_before bool
round_style float_round_style { round_to_nearest, … } //float_round_style是一個(gè)枚舉類型,具體可以參考
最通常的用法就是邊界檢查來確認(rèn)某一數(shù)據(jù)類型可以表示的最小值。接下來的代碼打印出了該系統(tǒng)平臺(tái)上short類型的最值:
#include
std::cout << "Maximum short value: " << std::numeric_limits
std::cout << "Minimum short value: " << std::numeric_limits
簡(jiǎn)單的類型聲明很容易理解:
int i
然而,有時(shí)也會(huì)有十分復(fù)雜的類型聲明:
double **d[8] //hmm...
char *(*(**foo [][8])())[] //augh! foo到底是什么?
為了理解上面的聲明,可以遵循下面的三個(gè)規(guī)則:
1.從變量名開始(在上例中就是d或者foo)
2.以數(shù)據(jù)類型結(jié)尾(double或者char)
3.如果可以的話向右,必須的話則向左(括號(hào)可能會(huì)讓你改變方向)
例如:
表達(dá)式 意義
double **d[8];
double **d[8]; d 是 … double
double **d[8]; d 是 8維數(shù)組 … double
double **d[8]; d 是 8維數(shù)組且成員為 指針且指向 … double
double **d[8]; d 是 8維數(shù)組且成員為 指針且指向 指針且指向 double
另外一個(gè)例子:
表達(dá)式 意義
char *(*(**foo [][8])())[]
char *(*(**foo [][8])())[] foo 是 … char
char *(*(**foo [][8])())[] foo 是 一個(gè)數(shù)組 … char
char *(*(**foo [][8])())[] foo 是 一個(gè)數(shù)組且成員為 8維數(shù)組 … char
char *(*(**foo [][8])())[] foo 是 一個(gè)數(shù)組且成員為 8維數(shù)組且成員為 指針且指向 … char
char *(*(**foo [][8])())[] foo 是 一個(gè)數(shù)組且成員為 8維數(shù)組且成員為 指針且指向 指針且指向 … char
char *(*(**foo [][8])())[] foo 是 一個(gè)數(shù)組且成員為 8維數(shù)組且成員為 指針且指向 指針且指向 函數(shù)且返回 … char
char *(*(**foo [][8])())[] foo 是 一個(gè)數(shù)組且成員為 8維數(shù)組且成員為 指針且指向 指針且指向 函數(shù)且返回 指針且指向 … char
char *(*(**foo [][8])())[] foo 是 一個(gè)數(shù)組且成員為 8維數(shù)組且成員為 指針且指向 指針且指向 函數(shù)且返回 指針且指向 數(shù)組 … char
char *(*(**foo [][8])())[] foo 是 一個(gè)數(shù)組且成員為 8維數(shù)組且成員為 指針且指向 指針且指向 函數(shù)且返回 指針且指向 數(shù)組且成員為 指針且指向 char
譯注:
我們也可以采用另外一種方法就是層層類型定義的方法來解讀,不過是從外向內(nèi)的.比如例子1:
typedef double * pDouble;
typedef pDouble* ppDouble;
typedef ppDouble a8ppDouble[8];
a8ppDouble d;
第二個(gè)例子:
typedef char * pchar;
typedef pchar apchar[];
typedef apchar * papchar;
typedef papchar fpapchar();
typedef papchar (*pfpapchar)();
typedef pfpapchar * ppfpapchar;
typedef ppfpapchar a8ppfpapchar[8];
typedef a8ppfpapchar aa8ppfpapchar[];
typedef aa8ppfpapchar foo;
附文:
下面是對(duì)Steve Friedl的參考文章的部分譯文,因?yàn)檫@里也同樣的是解說這兩個(gè)例子,不過對(duì)于規(guī)則上述說更詳細(xì)。
基本和派生類型
基本類型就是上邊提到的那些基本類型,這里還包括了struct,enum和union(譯注:因?yàn)檫@個(gè)說明是針對(duì)c語(yǔ)言的,所以對(duì)于c++來說還要加上一個(gè)class類型)
一個(gè)聲明只能定義一種基本類型,并且它總是出現(xiàn)在聲明式的最左邊?;绢愋涂梢员慌缮愋蛿U(kuò)張或者說是修飾,并且c有三種派生類型:
* 指針且指向(pointer to...)
這里*表明這是一個(gè)指針,而且不言自明地它要指向某個(gè)東西
[] 數(shù)組且成員為(array of...)
數(shù)組可以是已定維數(shù)的--[10]--也可以是未定維數(shù)的--[],但是維數(shù)在我們理解聲明具體含義的時(shí)候不是那么重要。典型地我們會(huì)把維數(shù)包含在聲明里。這樣可以明了的說“數(shù)組且成員為”某些東西。
() 函數(shù)且返回(function returning...)
函數(shù)通常是由一對(duì)圓括號(hào)來表明的--盡管可能在里面發(fā)現(xiàn)參數(shù)類型。參數(shù)列表其實(shí)在我們理解聲明的時(shí)候是不重要的,可以忽略。應(yīng)該注意到的是函數(shù)的括號(hào)和分組改變優(yōu)先級(jí)的括號(hào)是不一樣的:分組括號(hào)總是包圍變量而函數(shù)括號(hào)卻總是在變量名(即函數(shù)名)的右邊。
如果函數(shù)不返回值則它是無(wú)意義的(我們可以使用void來表示返回為空)。
一個(gè)派生類型總是修飾一個(gè)基本變量或者另外一個(gè)派生變量。我們?cè)诶斫饴暶鞯臅r(shí)候一定要包括介詞(to,of,returning)。說“指針”而不是“指針且指向...”會(huì)導(dǎo)致你的聲明分離。
操作符的優(yōu)先級(jí)
幾乎每一個(gè)c程序員都很熟悉操作符的優(yōu)先級(jí)表。比如乘除的優(yōu)先級(jí)要高于加減,但是括號(hào)可以改變這個(gè)優(yōu)先級(jí)。這個(gè)對(duì)于通常的表達(dá)式很自然,但是這個(gè)規(guī)則也可以運(yùn)用到聲明語(yǔ)句中--它們是類型表達(dá)式而不是計(jì)算表達(dá)式。
數(shù)組符號(hào)[]和函數(shù)符號(hào)()比指針*有更高的優(yōu)先級(jí),這樣我們可以推導(dǎo)出一些規(guī)則(這個(gè)規(guī)則和上邊所提的是一樣的,這里不再啰嗦,離子的推衍也不再重復(fù))。
抽象聲明
C標(biāo)準(zhǔn)也支持抽象聲明。它可以用在需要類型描述但是又不需要實(shí)際變量的情況下--cast,拋擲,和作為sizeof的參數(shù)。比如:
int (*(*)())()
對(duì)于上邊的問題--從哪里開始,答案是找到一個(gè)變量名可以放得下的地方,然后把它當(dāng)成一個(gè)通常的聲明。只有一個(gè)地方可以放置這個(gè)變量名并且找到它也是直截了當(dāng)?shù)?。遵循以下語(yǔ)法規(guī)則:
- 在*的右邊
- 在[]的左邊
- 在函數(shù)操作符()的左邊
- 在分組括號(hào)()的內(nèi)部
由上面的例子我們可以看到有兩個(gè)地方符合前三條規(guī)則:
int (*(* • ) • ())()
但是如果考慮則四條,則只有左邊的位置符合了。
int (*(*foo)())()
它表示:
foo是 指針且指向 函數(shù)且返回 指針且指向 函數(shù)且返回 int
語(yǔ)義限制
注意不是所有的派生組合都被允許的.這樣就可能聲明一個(gè)合乎語(yǔ)法卻沒有語(yǔ)義內(nèi)涵的東西來:
--不能有 數(shù)組且成員為函數(shù)
使用 數(shù)組且成員為 指針且指向 函數(shù)且返回.... (譯注:但是我們知道函數(shù)的地址就是函數(shù)本身,所以可以說 數(shù)組且成員為 函數(shù)指針且返回)
--函數(shù)不能返回函數(shù)
同樣使用函數(shù)指針代替
--函數(shù)不能返回?cái)?shù)組
可以使用 函數(shù)且返回 指針且指向 數(shù)組且成員為...(譯注:同樣地我們知道數(shù)組名同時(shí)也是數(shù)組首元素的地址,還是該數(shù)組的地址)
--數(shù)組中只有最左的[]可以是未定義的
--void是限制類型,它只有在和指針*以及函數(shù)()在一起時(shí)才有效.