强制类型转换
* ~- t5 T8 a, h
强制类型转换是通过类型转换运算来实现的。其一般形式为: (类型说明符) (表达式) 其功能是把表达式的运算结果强制转换成类型说明符所表示的类型。例如: (float) a 把a转换为实型(int)(x+y) 把x+y的结果转换为整型在使用强制转换时应注意以下问题:
; r- i, e# d) ]0 I; }: M( x
1.类型说明符和表达式都必须加括号(单个变量可以不加括号),如把(int)(x+y)写成(int)x+y则成了把x转换成int型之后再与y相加了。
0 ^& l# J6 U( d' Y# |; n. L+ p2.无论是强制转换或是自动转换,都只是为了本次运算的需要而对变量的数据长度进行的临时性转换,而不改变数据说明时对该变量定义的类型。
2 i' V0 a: f: ^# j1 e) [: T" Q
main()
7 B: p7 {1 E- z4 k, O{
6 F' E" r. N8 X
float f=5.75;
' {" K8 p) f$ u& d
printf("(int)f=%d,f=%f\n",(int)f,f);
* j! A! q0 N. B5 z* F
}
! k5 n/ E1 a1 {5 m; d
f<--5.75
0 v8 s9 T$ i) x5 y, B8 u将float f强制转换成int f float f=5.75;printf("(int)f=%d,f=%f\n",(int)f,f); 本例表明,f虽强制转为int型,但只在运算中起作用, 是临时的,而f本身的类型并不改变。因此,(int)f的值为 5(删去了小数)而f的值仍为5.75。
) l: Y" T( j: U( E
$ i3 I9 O! R' \+ S基本运算符和表达式
# @4 x0 Z9 `1 S, N: p* F
$ ]7 z% M7 g+ F7 R. \7 d8 E" I
运算符的种类、优先级和结合性
/ e; k2 F! `; k
C语言中运算符和表达式数量之多, 在高级语言中是少见的。正是丰富的运算符和表达式使C语言功能十分完善。 这也是C语言的主要特点之一。
5 {+ g4 d2 T& I; P' s
C语言的运算符不仅具有不同的优先级, 而且还有一个特点,就是它的结合性。在表达式中, 各运算量参与运算的先后顺序不仅要遵守运算符优先级别的规定,还要受运算符结合性的制约, 以便确定是自左向右进行运算还是自右向左进行运算。 这种结合性是其它高级语言的运算符所没有的,因此也增加了C语言的复杂性。
0 r; {" p) t# D& s4 h, S f
, r! u! ?' i8 j4 s9 a运算符的种类C语言的运算符可分为以下几类:
& \3 m |$ y; T* C0 e T, F1.算术运算符
0 `2 x9 G& \: _! o6 @( z
用于各类数值运算。包括加(+)、减(-)、乘(*)、除(/)、求余(或称模运算,%)、自增(++)、自减(--)共七种。
9 a7 X% }3 t1 t6 Z7 Y
2.关系运算符
/ I+ w- h/ T R, ^0 a
用于比较运算。包括大于(>)、小于(<)、等于(==)、 大于等于(>=)、小于等于(<=)和不等于(!=)六种。
! q: c6 V) Z- n! D9 p4 i6 [3.逻辑运算符
9 N" F: S, N. z2 U% z- s) B+ @用于逻辑运算。包括与(&&)、或(||)、非(!)三种。
& j& F1 }- C/ C+ ?/ y- q# l( U1 ^! X
4.位操作运算符
2 o C. r3 w8 E+ y) @参与运算的量,按二进制位进行运算。包括位与(&)、位或(|)、位非(~)、位异或(^)、左移(<<)、右移(>>)六种。
$ U" k' D3 c( o5.赋值运算符
. l$ ?& U- k* n( f+ l1 }0 B4 q用于赋值运算,分为简单赋值(=)、复合算术赋值(+=,-=,*=,/=,%=)和复合位运算赋值(&=,|=,^=,>>=,<<=)三类共十一种。
8 i2 a) c2 M4 V! g6.条件运算符
3 d/ M9 Q# A. w这是一个三目运算符,用于条件求值(?

。
+ E$ G3 ?; G' Y7 t. [/ i7.逗号运算符
, M4 G/ G9 O8 N) L# |8 F3 w
用于把若干表达式组合成一个表达式(,)。
$ |% L4 h! w$ Y' X& y: A' b8 Z) C
8.指针运算符
- g; U9 a" ^; h, s; P7 k
用于取内容(*)和取地址(&)二种运算。
0 m. v8 m- a' b. r+ P2 j9.求字节数运算符
& B8 r0 j5 Q, O2 g( O( o# X# @8 R
用于计算数据类型所占的字节数(sizeof)。
& Z& ^9 L9 [0 Y8 ]8 ] t( ?9 c
10.特殊运算符
) S$ D% V; C+ r( Z( K: s
有括号(),下标[],成员(→,.)等几种。
2 d/ h/ V& i- M# h
+ y e. d: _2 {# _' _# u' N1 S优先级和结合性
, {, t9 X4 k* I: K6 I7 E6 `6 b
C语言中,运算符的运算优先级共分为15级。1级最高,15级最低。在表达式中,优先级较高的先于优先级较低的进行运算。 而在一个运算量两侧的运算符优先级相同时, 则按运算符的结合性所规定的结合方向处理。 C语言中各运算符的结合性分为两种,即左结合性(自左至右)和右结合性(自右至左)。例如算术运算符的结合性是自左至右,即先左后右。如有表达式x-y+z则y应先与“-”号结合, 执行x-y运算,然后再执行+z的运算。这种自左至右的结合方向就称为“左结合性”。而自右至左的结合方向称为“右结合性”。 最典型的右结合性运算符是赋值运算符。如x=y=z,由于“=”的右结合性,应先执行y=z再执行x=(y=z)运算。 C语言运算符中有不少为右结合性,应注意区别,以避免理解错误。
% Z# A h' O* I- P+ F6 a; w% `
, p+ B, k1 B; i) c: h2 x( w算术运算符和算术表达式基本的算术运算符
: c6 V' D V" d4 A" M* C1.加法运算符“+”加法运算符为双目运算符,即应有两个量参与加法运算。如a+b,4+8等。具有右结合性。
) V) ^$ t5 k/ Z" t1 K& X4 c2.减法运算符“-”减法运算符为双目运算符。但“-”也可作负值运算符,此时为单目运算,如-x,-5等具有左结合性。
! P# g1 k4 D$ ?7 q# P W3.乘法运算符“*”双目运算,具有左结合性。
! a8 y+ a; ?6 y1 [5 ]# M6 Y
4.除法运算符“/”双目运算具有左结合性。参与运算量均为整型时, 结果也为整型,舍去小数。如果运算量中有一个是实型,则结果为双精度实型。
5 P. a7 n- m& U9 Gvoid main(){
4 B* m/ p6 T& J8 g5 s$ U- q
printf("\n\n%d,%d\n",20/7,-20/7);
5 ~, a* \2 U: e h) S% F2 F, G* S7 {
printf("%f,%f\n",20.0/7,-20.0/7);
& @( x4 F/ {5 j$ S, B}
- x% h2 ^3 A( T4 `* ]. o G双目运算具有左结合性。参与运算量均为整型时, 结果也为整型,舍去小数。如果运算量中有一个是实型,则结果为双精度实型。 printf("\n\n%d,%d\n",20/7,-20/7);
% |; |# U+ {6 E7 G6 q- @
printf("%f,%f\n",20.0/7,-20.0/7);
3 \' o: E; E( B- h/ u5 b2 z: @6 Z
本例中,20/7,-20/7的结果均为整型,小数全部舍去。而20.0/7和-20.0/7由于有实数参与运算,因此结果也为实型。
: y4 l+ d3 `! n; P: J$ f
5.求余运算符(模运算符)“%”双目运算,具有左结合性。要求参与运算的量均为整型。 求余运算的结果等于两数相除后的余数。
9 v2 j3 R) L3 J: F2 T
void main(){
# o0 P4 r! }4 o! B }* Pprintf("%d\n",100%3);
% H% k4 ^+ d& ]8 z+ X+ A& {# }+ `0 r}
) d( n& M2 ^/ A' s* j: w. U# e+ M双目运算,具有左结合性。求余运算符% 要求参与运算的量均为整型。本例输出100除以3所得的余数1。
$ V5 \: [( @# ~3 p
. k) e8 j3 s j, u' z& K, [ F+ p6 U8 G自增1,自减1运算符
+ d7 R. n3 V6 z* _0 e n8 K% t: h
自增1运算符记为“++”,其功能是使变量的值自增1。自减1运算符记为“--”,其功能是使变量值自减1。自增1,自减1运算符均为单目运算,都具有右结合性。可有以下几种形式: ++i i自增1后再参与其它运算。--i i自减1后再参与其它运算。
7 A) A+ X# o$ j) x4 q0 d, q
i++ i参与运算后,i的值再自增1。
) ^* _6 n: b" N
i-- i参与运算后,i的值再自减1。
1 D4 A7 j' i8 X5 X在理解和使用上容易出错的是i++和i--。 特别是当它们出在较复杂的表达式或语句中时,常常难于弄清,因此应仔细分析。
5 G, C# j* H- I) `: k
void main(){
) m: f! V: i9 o% Y. L/ m
int i=8;
3 ]4 n0 j5 V: R0 j: L" z# B
printf("%d\n",++i);
; E+ Z% N7 [$ ~* oprintf("%d\n",--i);
& K$ H- h8 m& W
printf("%d\n",i++);
+ `! b7 P& O6 M( C
printf("%d\n",i--);
% R9 c# A& Z, Z8 [
printf("%d\n",-i++);
! E# {% | I, F6 D/ }3 K8 x. _printf("%d\n",-i--);
7 j; ^: I- M3 o. A) N: u7 O) y
} i<--8
' x \+ s H0 j5 D" [
i<--i+1
& n- R- r+ X2 z, S: b
i<--i-1
2 _6 Z. o& T4 ~4 Yi<--i+1
+ I B2 X$ L% Z, a% h, z) ?- H
i<--i-1
8 k7 X/ t W3 Q% L) o9 }i<--i+1
R+ X5 ]; ^( f% @- ]& }5 Z
i<--i-1 int i=8;
$ T4 o& l5 n" ~2 e3 h. mprintf("%d\n",++i);
& p3 R: m/ h0 e4 eprintf("%d\n",--i);
8 o. m) a5 b0 k' t- q$ m: rprintf("%d\n",i++);
2 M$ M$ e, x4 W3 z
printf("%d\n",i--);
/ E6 |7 P! b+ Y( Iprintf("%d\n",-i++);
) {4 k$ W/ W& g1 H, H0 W2 O
printf("%d\n",-i--);
; j* A1 c* \. L' ?
i的初值为8
# x& B' w. m/ x0 c第2行i加1后输出故为9;
) F" r: H3 {8 a! [3 y" T
第3行减1后输出故为8;
) k# `/ ?0 Q- y- d0 Y) |/ v0 W第4行输出i为8之后再加1(为9);
0 x3 g3 E4 Q- Z# s
第5行输出i为9之后再减1(为8) ;
; C/ \) l% Y, t0 Q% p" m- w
第6行输出-8之后再加1(为9);
6 S6 b; [- f! ?/ Q% a5 _第7行输出-9之后再减1(为8)
3 q) y+ g, M4 s1 @: m3 X# r; [
void main(){
5 X* U. c* r- ^+ ]int i=5,j=5,p,q;
7 }% e7 {( I$ r5 mp=(i++)+(i++)+(i++);
: M, s9 x( F& S2 `: Q+ x$ `
q=(++j)+(++j)+(++j);
2 o1 X3 h& A$ s: t. o" d
printf("%d,%d,%d,%d",p,q,i,j);
$ o z3 F, n( b2 A8 U: m
}
" `! s% ^( [8 v: _/ X. o
i<--5,j<--5,p<--0,q<--0
' W0 q5 Q) P6 x; X5 w1 O% T; @
i+i+i--->p,i+1-->i,i+1-->i,i+1-->i
, ^" e6 Z& o2 @( n' O
j+1->j,j+1->j,j+1->j,j+j+j->q int i=5,j=5,p,q;
' p' D0 W, ^- `
p=(i++)+(i++)+(i++);
. `% E- J" Z7 v* \5 y8 @$ r) f) M
q=(++j)+(++j)+(++j);
& Y: ~) ?! j- i+ ]' S/ e这个程序中,对P=(i++)+(i++)+(i++)应理解为三个i相加,故P值为15。然后i再自增1三次相当于加3故i的最后值为8。而对于q 的值则不然,q=(++j)+(++j)+(++j)应理解为q先自增1,再参与运算,由于q自增1三次后值为8,三个8相加的和为24,j的最后值仍为8。算术表达式表达式是由常量、变量、函数和运算符组合起来的式子。 一个表达式有一个值及其类型, 它们等于计算表达式所得结果的值和类型。表达式求值按运算符的优先级和结合性规定的顺序进行。 单个的常量、变量、函数可以看作是表达式的特例。