C語言中的lvalue, rvalue

來源:互聯網
上載者:User

http://sunxiunan.com/?p=1628

 

lvalue算是C語言裡面不怎麼太容易說清楚的概念,我們上學的時候多半稱之為left-value左值,對應的還有在C++標準中的rvalue,也就是右值。

在wiki百科上http://en.wikipedia.org/wiki/Value_%28computer_science%29 解釋了一些。

首先什麼是value?value也好object也好在電腦內部的表示都是0和1,沒有什麼區別,某一塊記憶體位址的資料,按照整數解釋是一個值,按照class CObject解釋又是另外一個值,浮點數也好字串也好,如果光看這個記憶體位址裡面的資料是沒法看出什麼究竟的。所以需要編譯器做一些處理在某個地方記錄下來類型資訊。

上面文字翻譯成中文就是lvalue是程式運行時可以通過地址(address)資訊編程存取的值(比如通過&操作符),意味著他們是變數或者可以提領(dereferenced,通常用*操作符)某一塊特定記憶體位置。在C++標準中說明:不是lvalue的值就是rvalue。我們不能把rvalue作為lvalue使用,但是反過來可以,比如int a = b; 其中變數b可以為lvalue。

在偉大的K&R第二版中197頁寫道:一個對象是被命名的儲存地區或者被指向一Block Storage地區(an object is a named or pointed to region of storage);一個lvalue是一個指向對象的運算式(an lvalue is an expression referring to an object),(!!注意lvalue是一個運算式,這在後面例子中會體現出來)。。。lvalue這個名字來自賦值運算式E1 = E2,其中左邊的運算元E1必須是一個lvalue。

在Dan Saks的文章中提到,一個rvalue之所以不引用一個object,不是因為不能,而是因為不需要(Conceptually, an rvalue is just a value; it doesn’t refer to an object. In practice, it’s not that an rvalue can’t refer to an object. It’s just that an rvalue doesn’t necessarily refer to an object. Therefore, both C and C++ insist that you program as if rvalues don’t refer to objects.)

我們拿int n = 1; 來做說明,如果1是一個lvalue,那麼產生的彙編代碼類似下面這樣:

one: .word 1 
      … 
      mov (one), n

實際上對於大多數機器而言,其實是對n直接操作,類似:

mov #1, n

在這裡1沒有像我們想象的那樣指向一個object(如one),而是直接就操作了。甚至還有的機器產生彙編代碼如:

clr n 
     inc n

先把n清零,然後增加n的值,這裡面根本就沒有出現1。

MSDN部落格上http://blogs.msdn.com/vcblog/archive/2009/02/03/rvalue-references-c-0x-features-in-vc10-part-2.aspx

有一篇非常詳細的文字解釋c++中的lvalue,rvalue,有興趣的可以去看看。其中最為重要的一句話就是“another way to determine whether an expression is an lvalue is to ask "can I take its address?".  If you can, it’s an lvalue.  If you can’t, it’s an rvalue. ”翻譯為中文就是“決定一個運算式是否是lvalue的方法可以是:我能不能擷取它的地址?如果可以,那就是lvalue,否則就是rvalue。”另外需要著重說明的是,lvalue一定可以擷取地址,但不要求是可以修改的(如const,如後面提到的字串字面值)。

加法操作一直返回一個rvalue,比如m+ 1 = n; 這就沒法編譯通過,因為 m + 1 這個運算式是一個rvalue。

針對lvalue中的l,我們也可以認為是location,其實也就是能不能擷取地址的另一種意思,這也就是為何數字型字面值以及非引用型函數不是lvalue的原因。

char(*pchar)[] = &("aabbccddee");

有些文章說字串字面值(string literals)算是lvalue,但是不能改變這個值,上面的代碼就是一個示範。

*&("aabbccddee") = ‘a’;

這個指派陳述式在VC6下編譯通過(這是錯誤的!),在Xcode中出錯提示“對read-only location賦值”,在VC2008下提示"left operand must be l-value"。所以還是建議大家用新版本的編譯器來學習工作,否則很容易造成誤解。

下面我舉幾個例子,大家看看能否判斷是lvalue還是rvalue。

obj , *ptr , ptr[index] , ++x, 1729 , x + y , std::string("meow") , x++

在VC6中編寫一個最簡單的操作台程式,輸入下面代碼:

int main(int argc, char* argv[]) 
    { 
        int obj = 0; 
        int* ptr = &obj; 
        int x = 1; 
        int* ptr2 = &(++x); 
        int* ptr3 = &(x++); 
        return 0; 
    }

編譯結果是testconsole1.cpp(12) : error C2102: ‘&’ requires l-value,第12行就是int* ptr3 = &(x++);

稍微修改一下這段代碼讓它做一下deference操作:

int main(int argc, char* argv[]) 

    int x = 1;    
    *&(++x) = 9; 
    *&(x++) = 10; 
    return 0; 
}

同樣也是在x++這一行編譯不通過。儘管x++或者++x並沒有修改x的記憶體位置,但x++這種形式就是rvalue,沒法對這個運算式進行提領(*)操作。很有意思吧,這裡面應該還有更說得通的理由,希望有高人指點一下。(在msdn blog上的解釋是x++這種形式會產生臨時對象,但那是針對C++而言,不知道對於C來說是不是也是同一種解釋)

既然是運算式,函數也是運算式一種形式,是不是也可以作為lvalue出現呢?stackoverflow上有一個問題裡面舉了一個很有意思的例子http://stackoverflow.com/questions/579421/often-used-seldom-defined-terms-lvalue

#include "stdafx.h" 
      static int aa = 0; 
      int* func() {   
         aa++; 
         return &aa; 
       } 
int main(int argc, char* argv[]) 

    *func() = 42; 
    printf("%d", aa); 
    return 0; 
}

在VC6下運行結果為43(?!),而VC2008以及Mac XCode3.1運行結果為42,在這裡VC6好像是有一些問題啊。當然我們期望aa結果應該是42.

相關參考文檔:ISO C99標準

《The New C Standard》http://www.coding-guidelines.com/cbook/cbook1_2.pdf

C Programming Language》K&R第二版

http://publications.gbdirect.co.uk/c_book/

http://www.cs.dartmouth.edu/~chris/cs23/summit-intro/

http://www.embedded.com/story/OEG20010518S0071

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.