2012-06-19 49 views
1

在C中,有沒有一種方法來識別右值和左值?C如何識別右值和左值?

其中有些是容易的身份說,在分配,左值是左值,並在右邊的值是右值。

但是其他情況下,使用這種規則進行識別是困難的。

例如:*p++i++(其中p是指向整數的指針,i是整數) - 如何識別它是右值還是左值? 上下文是++*p++作品而++i++不會因爲i++是一個右值(如告訴嚴重的傢伙)。

如何識別一個表達式右值和左值?

+0

我覺得這是一個很好的問題,但你所說的「識別」的意思?你想要一個全面的操作列表,以及它們是否返回l或r值?從函數sig中告訴的一種方法?一種查看每行代碼是否有左值或右值的方法? – djechlin

+0

@djechlin,通過「識別」我的意思是,我是否可以通過查看源代碼(無需補充)來確定代碼片段是否工作正常。沒有一個全面的清單,是否有方法可以用來識別右值和左值?但是,如果有一個全面的列表存在,這對我來說很有用。 –

+0

我想你應該從忘記「右值=右值」開始,這顯然是錯誤的。 – qdii

回答

2

左值(從左手側(左軸)值)的東西,是指一個存儲器(或寄存器)存儲,以及是否可以將值分配給。 *p++左值,因爲它是一個解除引用的指針(即,指的是在存儲器中的位置即ptr點而ptr本身的值是該位置的地址)和++*ptr++實際上意味着:*ptr = *ptr + 1; ptr = ptr + 1; - 它遞增的值指向通過ptr,然後遞增指針值本身。 i++不是左值因爲它是i遞增1的值,而不是指一個位置在存儲器中。您可以將這些值視爲最終值 - 它們不能進一步修改,只能用作值賦予左值。這就是爲什麼他們被稱爲右值(從右側(RHS)值)。

LHS和RHS指賦值表達式A = B;的兩側。 A是LHS,B是RHS。

0

從的Deitel和Deitel公司:

變量名被說成是左值(爲「左值」),因爲它們可以在賦值運算符的左側被使用。據說常量是右值(對於「正確的值」),因爲它們只能在賦值運算符的右側使用。請注意,左值也可以用作右值,但反之亦然。

x = 3; /* here, x is an lvalue */ 
c = x; /* and in the next line it is an rvalue */ 
+0

聽起來像他知道這一點,並想知道更全面的方法來識別它們。 – djechlin

2

術語左值已與C(和結轉到C++和稍後展開)。沒有右值開始。我的草案(N1570)確實列出了兩次出現的術語右值 - 腳註#64中的一次,並且在索引中一次。

簡而言之:在C世界中,您有兩種類型的對象 - 左值以及其他所有內容。

注意腳註是不是標準的一部分,但他們能提供一些有用的見解。這裏不用腳註64:

64)名稱「‘左值’」從分配表達E1 = E2,其中,所述左操作數 E1需要是一個(可修改)的左值來最初。它可能更好地被認爲是代表對象的'定位器值'的 。有時稱爲「右值」的是在該國際標準中將 描述爲「表達式的值」。

左值的一個明顯的例子是一個對象的標識符。作爲進一步的例子,如果E是一個一元 表達式是一個指針到一個對象,* E是一個左值,指定的對象,其中E點。

這給出了一個良好的開端。現在,請記住,表達式是從對象(和操作符)構建而成的,但我們會稍微介紹一下),並且在處理對象時需要擔心兩件基本的事情:類型和值。讓我們看看是什麼的標準說一下那麼類型限制(6.3.2.1/p1):

左值是潛在 指定的一個對象中的表達(與空隙比其他的對象類型);如果64)一個左值在評估時不會指定一個對象,其行爲是未定義的。

此外,請注意下一行是很重要的:

當對象被說成具有特定的類型,類型是由用於指定該對象的左值指定 。

所以,一個左值可以用作類型的替代品(我們會看到這太)。接下來,就讓我們一起來看看上下文,其中一個對象左值(6.3.2.1/2):

當它是sizeof操作符,該_Alignof操作者的操作,在 一元運算符&,++運算符, - 操作符或左操作數。運營商 或轉讓運營商

因此,這些是您需要密切關注的運營商。在所有其他情況:

不具有陣列類型被轉換爲存儲在指定對象中的 值(並且不再左值)左值;這被稱爲左值 轉換。

有兩種特殊類型:數組和功能指示器。這些衰變即被轉換爲與類型的表達式「指向 到陣列對象的初始元素,是不是左值/「指針函數返回類型」‘指針爲類型’」。(請記住,我們已經暫停的事實,左值可以作爲類型的工作 - 這是他們做什麼與sizeof_Alignof!)