C和指针 第5章 操作符和表达式 5.1 操作符
操作符和表達式
?? ?C提供了編程語言應該擁有的所有操作符,它甚至提供了一些令人意想不到的操作符。事實上,C被許多人所詬病的一個缺點就是它有品類繁多的操作符。此外,C的許多操作符具有其他語言的操作符無可抗衡的價值,這也是C適用于開發(fā)范圍極廣的應用程序的原因之一。
?? ?本章還將討論表達式求值的規(guī)則,包括操作符優(yōu)先級和算術轉(zhuǎn)換。
5.1 操作符
?? ?這里按照操作符的功能或它們的使用方式來對它們進行分類。為了便于參考,按照優(yōu)先級對它們進行分組會更方便一些。
?? ?5.1.1 算術操作符
?? ?C提供了所有常用的算術操作符:
?? ?+ - * / %
?? ?除了%操作符,其余幾個操作符都是既適用于浮點類型,又適用于整數(shù)類型。當/操作數(shù)的兩個操作數(shù)都是整數(shù)時,它執(zhí)行整除運算,在其他情況下則執(zhí)行浮點數(shù)除法。%為取模操作符,它接受兩個整型操作數(shù),把左操作數(shù)除以右操作數(shù),但它返回的值是余數(shù)而不是商。
?? ?如果整除運算的任一操作數(shù)為負值,運算的結(jié)果是由編譯器定義的。
?? ?5.1.2 移位操作符
?? ?匯編語言程序員對于移位操作已經(jīng)是非常熟悉了。移位操作只是簡單地把一個值的位向左或向右移動。在左移位中,值最左邊的幾位被丟棄,右邊多出來的幾個空位則由0補齊。
?? ?右移位操作存在一個左移位操作不曾面臨的問題:從左邊移入新位時,可以選擇兩種方案:一種是邏輯移位,左邊移入的位用0填充;另一種是算術移位,左邊移入的位由原先該值的符號位決定,符號位為1則移入的位均為1,符號位為0則移入的位均為0,這樣能夠保證原數(shù)的正負形式不變。算術左移和邏輯左移是相同的,它們只在右移時不同,而且只有當操作數(shù)是負值時才不一樣。
?? ?左移位操作符為<<,右移位操作符為>>。左操作符的值將移動由右操作數(shù)指定的位數(shù)。兩個操作數(shù)必須是整型類型。
?? ?警告:
?? ?標準規(guī)定無符號值執(zhí)行的所有移位操作都是邏輯移位,但對于有符號值,到底是采用邏輯移位還是算術移位則取決于編譯器。因此,一個程序如果使用了有符號數(shù)的右移位操作,它就是不可移植的。
?? ?警告:
?? ?注意類似這種形式的移位:
?? ?a << -5
?? ?在某臺機器上,這個表達式實際執(zhí)行左移27位的操作。如果移位的位數(shù)比操作數(shù)的位數(shù)還要多,會發(fā)生什么情況呢?標準規(guī)定這類移位的行為是未定義的,所以它是由編譯器決定的。因此,應該避免使用這種類型的移位,因為它們的效果是不可預測的,使用這類移位的程序是不可移植的。
?? ?函數(shù)使用右移位操作來計數(shù)一個值中值為1的位的個數(shù)。它接受一個無符號參數(shù)(這是為了避免右移位的歧義),并使用%操作符判斷最右邊的一位是否非零。
?? ?/*
?? ?**這個函數(shù)返回參數(shù)值中值為1的位的個數(shù)。?
?? ?*/
?? ?int count_one_bits( unsigned value )
?? ?{
?? ??? ?int ones;
?? ??? ?/*
?? ??? ?**當這個值還有一些值為1的位時。?
?? ??? ?*/
?? ??? ?for( ones = 0; value != 0; value = value >> 1 ){
?? ??? ??? ?/*
?? ??? ??? ?**如果最低位的值為1,計數(shù)加1。
?? ??? ??? ?*/
?? ??? ??? ?if( value % 2 != 0 ){
?? ??? ??? ??? ?ones = ones + 1;
?? ??? ??? ?}
?? ??? ?}?? ?
?? ??? ?return ones;
?? ?}?
?? ?/* 5.1 count_1a.c */
?? ?5.1.3 位操作符
?? ?位操作符對它們的操作符的各個位執(zhí)行AND、OR和XOR(異或)等邏輯操作。當兩個位執(zhí)行AND操作時,如果兩個位都是1,結(jié)果為1,否則結(jié)果為0。當兩個位進行OR操作時,如果兩個位都是0,結(jié)果為0,否則結(jié)果為1。最后,當兩個位進行XOR操作時,如果兩個位不同,結(jié)果為1,如果兩個位相同,結(jié)果為0。
?? ?位操作符有:
?? ?& | ^
?? ?位的操縱
?? ?下面的表達式顯示了可以怎樣使用移位操作符和位操作符來操縱一個整型值中的單個位。這里假定bit_number為一整型值,它的范圍從0到整型值的位數(shù)減1,并且整型值的位從右向左計數(shù)。第1個例子把指定的位設置為1。
?? ?value = value | 1 << bit_number;
?? ?下一個例子把指定的位清0。
?? ?value = value & ~( 1 << bit_number );
?? ?這些表達式常常寫成|=和&=操作符的形式。最后,下面這個表達式對指定的位進行測試。如果該位已被設置為1,則表達式的結(jié)果為1,則表達式的結(jié)果為非零值。?
?? ?value & 1 << bit_number?
?? ?單目操作符~,它用于對其操作數(shù)進行求補運算,即1變?yōu)?,0變?yōu)?。
?? ?5.1.4 賦值操作符
?? ?賦值操作符,它用一個等號表示。賦值是表達式的一種,而不是某種類型的語句。所以,只要是允許出現(xiàn)表達式的地方,都允許進行賦值。例如:
?? ?x = y + 3;
?? ?包含兩個操作符:+和=。首先進行加法運算,所以=的操作數(shù)是變量x和表達式y(tǒng)+3的值。賦值操作符把右操作數(shù)的值存儲于左操作數(shù)指定的位置。但賦值也是個表達式,表達式就具有一個值。賦值表達式的值就是左操作數(shù)的新值,它可以作為其他賦值操作符的操作數(shù),例如:
?? ?a = x = y + 3;
?? ?賦值操作符的結(jié)合性(求值順序)是從右到左,所以這個表達式相當于:
?? ?a = ( x = y + 3 );
?? ?它的意思和下面的語句組合完全相同:
?? ?x = y + 3;
?? ?a = x;
?? ?合法的較為復雜的例子。
?? ?r = s + ( t = u - v ) / 3;
?? ?相當于
?? ?t = u - v;
?? ?r = s + t / 3;
?? ?這種寫法更易于閱讀和調(diào)試。
?? ?警告:
?? ?在下面的語句中,認為a和x被賦予相同的值的說法是不正確的:
?? ?a = x = y + 3;
?? ?如果x是一個字符型變量,那么y+3的值就會被截去一段,以便容納于字符類型的變量中。那么a所賦的值就是這個被截短后的值。
在下面這個常見的錯誤中,這種截短正是問題的根源所在:
?? ?char ch;
?? ?...
?? ?while( ( ch = getchar() ) != EOF) ...
?? ?EOF需要的位數(shù)比字符型所能提供的位數(shù)要多,這也是getchar返回一個整型值而不是字符值的原因。然而,把getchar的返回值首先存儲于ch中將導致它被截短。然后這個被截短的值被提升為整型并與EOF進行比較。當這段存在錯誤的代碼在使用有符號字符集的機器上運行時,如果讀取了一個值位\377的字節(jié),循環(huán)將會終止,因為這個值截短再提升之后與EOF相等。當這段代碼在使用無符號字符集的機器上運行時,這個循環(huán)將永遠不會終止!
?? ?復合賦值符
?? ?到目前為止所介紹的操作符都還有一種復合賦值的形式:
?? ?+= -= *= /= %=
?? ?<<= >>= &= ^= |=
?? ?只討論+=操作符,因為其余操作符與它非常類似,只是各自使用的操作符不同而已。+=操作符的用法如下:
?? ?a += expression
?? ?它讀作“把expression加到a”,它的功能相當于下面的表達式:
?? ?a = a + ( expression )
?? ?唯一不同之處是+=操作符的左操作數(shù)只求值一次。注意括號:它們確保表達式在執(zhí)行加法運算前已被完整求值,即使它內(nèi)部包含有優(yōu)先級低于加法運算的操作符。
?? ?存在兩種增加一個變量值的方法有何意義呢?K&R C設計者認為,復合賦值符可以讓程序員把代碼寫得更清楚一些。另外,編譯器可以產(chǎn)生更為緊湊的代碼。現(xiàn)在a=a+5和a+=5之間的差別不再那么明顯,而且現(xiàn)代的編譯器為這兩種表達式產(chǎn)生優(yōu)化代碼并無多大問題。
但請考慮下面的兩條語句,如果函數(shù)f沒有副作用,它們是等同的。
?? ?a[ 2 * ( y - 6 * f( x )) ] = a[ 2 * ( y - 6 * f( x )) ] + 1;?
?? ?a[ 2 * ( y - 6 * f( x )) ] += 1;
?? ?在第1種形式中,用于選擇增值位置的表達式必須書寫兩次,一次在賦值號的左邊,另一次在賦值號的右邊。由于編譯器無從知道函數(shù)f是否具有副作用,所以它必須兩次計算下標表達式的值。第2種形式效率更高,因為下標只計算一次。
?? ?提示:
?? ?+=操作符更重要的優(yōu)點是它使源代碼更容易閱讀和書寫。
?? ?使用復合賦值符來修改程序5.1。復合賦值符同時能簡化用于設置和清除變量值中單個位的表達式。
?? ?value |= 1 << bit_numbers;
?? ?value &= ~( 1 << bit_numbers);?
?? ?/*
?? ?**這個函數(shù)返回參數(shù)值中值為1的位的個數(shù)。?
?? ?*/
?? ?int count_one_bits( unsigned value )
?? ?{
?? ??? ?int ones;
?? ??? ?/*
?? ??? ?**當這個值還有一些值為1的位時。?
?? ??? ?*/
?? ??? ?for( ones = 0; value != 0; value >>= 1 ){
?? ??? ??? ?/*
?? ??? ??? ?**如果最低位的值為1,計數(shù)加1。
?? ??? ??? ?*/
?? ??? ??? ?if( value % 2 != 0 ){
?? ??? ??? ??? ?ones += 1;
?? ??? ??? ?}
?? ??? ?}?? ?
?? ??? ?return ones;
?? ?}?
?? ?//程序5.2 count_lb.c
?? ?5.1.5 單目操作符
?? ?C有一些單目操作符,也就是只接受一個操作數(shù)的操作符。它們是
?? ?! ++ - & sizeof
?? ?~ -- + * (類型)
?? ?!操作符對它的操作數(shù)執(zhí)行邏輯反操作:如果操作數(shù)為真,其結(jié)果為假;如果操作數(shù)為假,其結(jié)果為真。和關系運算符一樣,這個操作符實際上產(chǎn)生一個整型結(jié)果:0或1。?
?? ?~操作符對整型類型的操作數(shù)進行求補操作,操作數(shù)中所有原先為1的位變?yōu)?,所有原先為0的位變?yōu)?。
?? ?-操作符產(chǎn)生操作數(shù)的負值。
?? ?+操作符產(chǎn)生操作數(shù)的值;換句話說,它什么也不干。之所以提供這個操作符,是為了與-操作符組成對稱的一對。
?? ?&操作符產(chǎn)生它的操作數(shù)的地址。
?? ?int a, *b; /*a是一個整型變量,b是一個指向整型的指針*/?
?? ?...
?? ?b = &a; /*&操作符取變量a的地址,并把它賦值給指針變量。*/
?? ?*操作符是間接訪問操作符,它與指針一起使用,用于訪問指針所指向的值。
?? ?表達式b的值是變量a的地址,但表達式*b的值則是變量a的值。
?? ?sizeof操作符判斷它的操作數(shù)的類型長度,以字節(jié)為單位。操作數(shù)既可以是個表達式(常常是單個變量),也可以是兩邊加上括號的類型名。例如:
?? ?sizeof(int) sizeof x
?? ?第1個表達式返回整型變量的字節(jié)數(shù),其結(jié)果取決于所使用的的環(huán)境。第2個表達式返回變量x所占據(jù)的字節(jié)數(shù)。注意,從定義上說,字符變量的長度為1字節(jié)。如果sizeof的操作數(shù)是個數(shù)組名,則返回該數(shù)組的長度,以字節(jié)為單位。在表達式兩邊加上括號也是合法的,如下所示:
?? ?sizeof(x)
?? ?這是因為括號在表達式中總是合法的。在判斷表達式長度時,并不需要對表達式進行求值,所以sizeof(a = b + 1)并沒有向a賦任何值。
?? ?(類型)操作符被稱為強制類型轉(zhuǎn)換(cast),它用于顯式地把表達式的值轉(zhuǎn)換為其他類型。例如,為了獲得整型變量a的對應的浮點數(shù)值,可以這樣寫:
?? ?(float)a;
?? ?“強制類型轉(zhuǎn)換”具有很高的優(yōu)先級,把強制類型轉(zhuǎn)換放在一個表達式前面只會改變表達式中第1個項目的類型,如果要對整個表達式的結(jié)果進行強制類型轉(zhuǎn)換,就必須把整個表達式用括號括起來。
?? ?遞增操作符++和遞減操作符--都有兩個變型,分別為前綴形式和后綴形式。兩個操作符的任一變型都需要一個變量而不是表達式作為它的操作數(shù)。實際上,這個限制并非那么嚴格。這個操作符實際上只要求操作數(shù)必須是一個“左值”,但目前我們還沒有討論這個話題。這個限制要求++或--操作符只能作用于可以位于賦值符號左邊的表達式。
?? ?前綴形式的++操作符出現(xiàn)在操作數(shù)的前面。操作數(shù)的值被增加,而表達式的值就是操作數(shù)增加后的值。后綴形式的++操作符出現(xiàn)在操作數(shù)的后面。操作數(shù)的值仍被增加,但表達式的值是操作數(shù)增加前的值。在操作數(shù)之前的操作符在變量值被使用之前增加它的值;在操作數(shù)之后的操作符在變量值被使用之后增加它的值。--操作符的工作原理與此相同,只是它所執(zhí)行的是減值操作而不是增值操作。
?? ?int a, b, c, d;
?? ?...
?? ?a = b = 10; ? ?a和b得到值10?
?? ?c = ++a; ? ? ? a增加至11,c得到的值為11?
?? ?d = b++; ? ? ? b增加至11,但d得到的值仍為10?
?? ?抽象地說,前綴和后綴形式的增值操作都復制一份變量值的拷貝。用于周圍表達式的值正是這份拷貝(在上面的例子中,“周圍表達式”是指賦值操作)。前綴操作符在進行復制之前增加變量的值,后綴操作符在進行復制之后才增加變量的值。這些操作符的結(jié)果不是被它們所修改的變量,而是變量值的拷貝,認識到這一點非常重要。它之所以重要,是因為它解釋了為什么不能像下面這樣使用這些操作符:
?? ?++a = 10;
?? ?++a的結(jié)果是a值的副本,并不是變量本身,因此無法向一個值進行賦值。
?? ?5.1.6 關系操作符
?? ?關系操作符用于測試操作數(shù)之間的各種關系。C提供了所有常見的關系操作符。不過,這組操作符里面存在一個陷阱。這些操作符是:
?? ?> >= < <= == !=
?? ?!=操作符用于測試“不相等”,而==操作符用于測試“相等”。這些操作符產(chǎn)生的結(jié)果都是一個整型值,而不是布爾值。如果兩端的操作數(shù)符合操作符指定的關系,表達式的結(jié)果是1;如果不符合,表達式的結(jié)果是0。關系表達式的結(jié)果是整型,所以它可以賦值給整型變量,但通常它們在if或while語句中用作測值表達式。請記住這些語句的工作方式:表達式的結(jié)果如果是0,它被認為是假;表達式的結(jié)果如果是任何非零值,它被認為是真。所有關系操作符的工作原理相同,如果操作符兩端的操作數(shù)不符合它指定的關系,表達式的結(jié)果為0。因此,單純從功能上說,我們并不需要額外的布爾型數(shù)據(jù)類型。
?? ?C用整型來表示布爾類型,這直接產(chǎn)生了一些簡寫方法,它們在表達式測值中極為常用。
?? ?if( expression != 0 )...
?? ?if( expression )...?
?? ?
?? ?if( expression == 0 )...
?? ?if( !expression )...
?? ?在每對語句中,兩條語句的功能是相同的。測試“不等于0”既可以用關系操作符來實現(xiàn),也可以簡單地通過測試表達式的值來完成。類似地,測試“等于0”也可以通過測試表達式的值,然后再取結(jié)果值的邏輯反來實現(xiàn)。使用最后一種形式時必須多加小心。由于!操作符的優(yōu)先級很高,因此如果表達式內(nèi)包含了其他操作符,最好把表達式放在一對括號內(nèi)。
?? ?警告:
?? ?在C中,必須使用雙等號==來執(zhí)行這個比較,單個=號用于賦值操作。
?? ?這里的陷阱在于:在測試相等性的地方出現(xiàn)賦值符是合法的,它并非是一個語法錯誤。這個不幸的特點正是C不具備布爾類型的不利之處。這兩個表達式都是合法的整型表達式,所以它們在這個上下文環(huán)境中都是合法的。
?? ?x = get_some_value();
?? ?if( x = 5 )
?? ??? ?執(zhí)行某些任務
?? ?x從函數(shù)獲得一個值,但接下來我們把5賦值給x,而不是把x與字面值5進行比較,從而丟失了從函數(shù)獲得的那個值。這個結(jié)果顯然不是程序員的意圖所在。但是,這里還有一個問題。由于表達式的值是x的新值(非零值),因此if語句將始終為真。
?? ?應該養(yǎng)成一個習慣,在進行相等性測試比較時,要檢查一下所書寫的確實是雙等號符。如果發(fā)現(xiàn)程序運行不正常,趕快檢查一下比較操作符有沒有寫錯,這可能節(jié)省大量的調(diào)試時間。
?? ?5.1.7 邏輯操作符
?? ?邏輯操作符有&&和||。它們對表達式求值,測試它們的值是真還是假。
?? ?expression1 && expression2
?? ?如果expression1和expression2的值都是真的,那么整個表達式的值也是真的。如果兩個表達式中任何一個為假,那么整個表達式的值變?yōu)榧佟?br /> ?? ?這個操作符存在一個有趣之處,就是它會控制子表達式求值的順序。例如:
?? ?a > 5 && a < 10
?? ?&&操作符的優(yōu)先級比>和<操作符的優(yōu)先級都要低,所以子表達式是按下面這種方式進行組合的:
?? ?(a > 5) && (a < 10)
?? ?但它仍然會對兩個關系表達式施加控制。下面是它的工作原理:&&操作符的左操作數(shù)總是首先進行求值,如果它的值為真,然后就緊接著對右操作數(shù)進行求值。如果左操作數(shù)的值為假,那么右操組數(shù)不再進行求值,因為整個表達式的值肯定是假的,右操作數(shù)的值已無關緊要。||操作符也具有相同的特點,它首先先對左操作數(shù)進行求值,如果它的值為真,右操作數(shù)便不再求值,因為整個表達式的值此時已經(jīng)確定。這個行為常常被稱為“短路求值”(short-circuited evaluation)。?
?? ?表達式的順序必須確保正確,這一點非常有用。
?? ?if( x >= 0 && x < MAX && array[x] == 0 ) ...
?? ?在C中,這段代碼首先檢查x的值是否在數(shù)組下標的合法范圍內(nèi)。如果不是,代碼中的下標引用表達式便被忽略。
?? ?警告:
?? ?位操作符常常與邏輯操作符混淆,但它們是不可互換的。它們之間的第一個區(qū)別是||和&&操作符具有短路性質(zhì),即如果表達式的值根據(jù)左操作數(shù)便可決定,它就不再對右操作數(shù)進行求值。與之相反,|和&操作符兩邊的操作數(shù)都需要進行求值。
?? ?其次,邏輯操作符用于測試零值和非零值,而位操作符用于比較它們的操作數(shù)中對應的位。這里有一個例子:
?? ?if( a < b && c > d )...
?? ?if( a < b & c > d )...
?? ?因為關系操作符產(chǎn)生的或者是0,或者是1,所以這兩條語句的結(jié)果是一樣的。但是,如果a是1而b是2,下一對語句就不會產(chǎn)生相同的結(jié)果:
?? ?if( a && b )...
?? ?if( a & b)...
?? ?因為a和b都是非零值,所以第1條語句的值是真,但第2條語句的值卻是假,因為在a和b的位模式中,沒有一個位在兩者中的值都是1。
?? ?5.1.8 條件操作符
?? ?條件操作符接受3個操作數(shù),它也會控制子表達式的求值順序。下面是它的用法:
?? ?expression1 ? expression2 : expression3
?? ?條件操作符的優(yōu)先級非常低,所以它的各個操作數(shù)即使不加括號,一般也不會有問題。但是,為了清楚起見,人們還是傾向于在它的各個子表達式兩端加上括號。
?? ?首先計算的是expression1,如果它的值為真(非零值),那么整個表達式的值就是expression2的值,expression3不會進行求值。但是,如果expression1的值是假(零值),那么整個條件語句的值就是expression3的值,expression2不會進行求值。
? ? 提示:
?? ?什么時候要用到條件操作符呢?這里有兩個程序片段:
?? ?if( a > 5)?? ??? ??? ??? ?b = a > 5 ? 3 : -20;
?? ??? ?b = 3;
?? ?else
?? ??? ?b = -20;?
?? ?兩段代碼所實現(xiàn)的功能完全相同,但左邊的代碼要兩次書寫“b=”。當然,這沒什么大不了,在這種場合使用條件操作符并無優(yōu)勢可言。
?? ?但是,請看下面這條語句:
?? ?if( a > 5 )
?? ??? ?b[2 * c + d( e / 5 )] = 3;
?? ?else
?? ??? ?b[2 * c + d( e / 5 )] = -20;
?? ?在這里,常常的下標表達式需要寫兩次,確實令人討厭。如果使用條件操作符,看上去就清楚得多:
?? ?b[2 * c + d( e / 5 )] = a > 5 ? 3 : -20;
?? ?在此例中,使用條件操作符出現(xiàn)打字錯誤的可能性也比之前一種寫法要低,而且條件操作符可能會產(chǎn)生較小的目標代碼。
?? ?5.1.9 逗號操作符
?? ?逗號操作符的用法如下:
?? ?expression1, expression2, ... , expressionN
?? ?逗號操作符用于將兩個表達式分隔開來。這些表達式自左向右逐個進行求值,整個逗號表達式的值就是最后那個表達式的值。例如
?? ?if( b + 1, c / 2, d > 0 )
?? ?如果d的值大于0,那么整個表達式的值就為真。前兩個表達式的求值毫無意義,它們的值只是簡單地丟棄。但是,請看下面的代碼:
?? ?a = get_value();
?? ?count_value( a );
?? ?while( a > 0 ){
?? ??? ?...
?? ??? ?a = get_value();
?? ??? ?count_value( a );
?? ?}?
?? ?可以使用逗號操作符將a = get_value()和count_value( a )寫入到while的表達式中,而且只需要寫入一次。
?? ?while( a = get_value(), count_value( a ), a > 0){
?? ??? ?...
?? ?}?
?? ?也可以使用內(nèi)嵌的賦值形式,如下所示:
?? ?while( count_value( a = get_value() ), a > 0 ){
?? ??? ?...
?? ?}?
?? ?提示:
?? ?現(xiàn)在,循環(huán)中用于獲得下一個值的語句只需要出現(xiàn)一次。逗號操作符使源程序更易于維護。如果用于獲得下一個值的方法在將來需要改變,那么代碼中只有一個地方需要修改。
?? ?但是,面對這個優(yōu)點,我們很容易“用力過猛”。所以在只使用逗號操作符之前,要問問自己它能不能讓程序在某方面表現(xiàn)更出色。如果答案是否定的,就不要使用它。順便說一下,“更出色”并不包括“更炫”“更酷”或“令人印象更深刻”。
?? ?這里有一個技巧,你偶爾可能會看到:
?? ?while( x < 10 )
?? ??? ?b += x,
?? ??? ?x += 1;
?? ?逗號操作符把兩條賦值語句整合成一條語句,從而避免了在它們兩端加上花括號。不過,這并不是一個好做法,因為逗號和分號的區(qū)別過于細微,人們很難注意到第一個賦值后面是一個逗號而不是分號。
?? ?5.1.10 下標引用、函數(shù)調(diào)用和結(jié)構(gòu)成員
?? ?下標引用操作符是一對方括號。下標引用操作符接受兩個操作數(shù):一個數(shù)組名和一個索引值。事實上,下標引用并不限于數(shù)組名。C的下標值總是從零開始,并且不會對下標值進行有效性檢查。除了優(yōu)先級不同,下標引用操作符和間接訪問表達式總是等價的。它們的映像關系如下:
?? ?array[下標]
?? ?*(array + (下標))?
?? ?下標引用實際上是以后面這種形式實現(xiàn)的。
?? ?函數(shù)調(diào)用操作符接受一個或多個操作數(shù)。它的第一個操作數(shù)是希望調(diào)用的函數(shù)名,剩余的操作數(shù)就是傳遞給函數(shù)的參數(shù)。把函數(shù)調(diào)用以操作符的方式實現(xiàn),意味著“表達式”可以代替“常量”作為函數(shù)名,事實也確實如此。
?? ?.和->操作符用于訪問一個結(jié)構(gòu)的成員。如果s是個結(jié)構(gòu)變量,那么s.a就訪問s中名叫a的成員。如果有一個指向結(jié)構(gòu)的指針而不是結(jié)構(gòu)本身,且欲訪問它的成員,就需要使用->操作符而不是.操作符。?
總結(jié)
以上是生活随笔為你收集整理的C和指针 第5章 操作符和表达式 5.1 操作符的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: VLAN的划分以及三层交换机理论,OMG
- 下一篇: 一个即将走向社会的软件技术专业学生的感想