【轉】左值與右值

出處:http://www.embedded.com/electronics-blogs/programming-pointers/4023341/Lvalues-and-Rvalues

C and C++ enforce subtle differences on the expressions to the left and right of the assignment operator

If you've been programming in either C or C++ for a while, it's likely that you've heard the terms?lvalue?(pronounced "ELL-value") and?rvalue?(pronounced "AR-value"), if only because they occasionally appear in compiler error messages. There's also a good chance that you have only a vague understanding of what they are. If so, it's not your fault.

Most books on C or C++ do not explain lvalues and rvalues very well. (I looked in a dozen books and couldn't find one explanation I liked.) This may be due to of the lack of a consistent definition even among the language standards. The 1999 C Standard defines lvalue differently from the 1989 C Standard, and each of those definitions is different from the one in the C++ Standard. And none of the standards is clear.

Given the disparity in the definitions for lvalue and rvalue among the language standards, I'm not prepared to offer precise definitions. However, I can explain the underlying concepts common to the standards.

As is often the case with discussions of esoteric language concepts, it's reasonable for you to ask why you should care. Admittedly, if you program only in C, you can get by without understanding what lvalues and rvalues really are. Many programmers do. But understanding lvalues and rvalues provides valuable insights into the behavior of built-in operators and the code compilers generate to execute those operators. If you program in C++, understanding the built-in operators is essential background for writing well-behaved overloaded operators.

Basic concepts
Kernighan and Ritchie coined the term lvalue to distinguish certain expressions from others. In The?C Programming Language?(Prentice-Hall, 1988), they wrote "An object is a manipulatable region of storage; an lvalue is an expression referring to an object....The name 'lvalue' comes from the assignment expression?E1 = E2?in which the left operand?E1?must be an lvalue expression."

In other words, the left and right operands of an assignment expression are themselves expressions. For the assignment to be valid, the left operand must refer to an object-it must be an lvalue. The right operand can be any expression. It need not be an lvalue. For example:

int n;

declares?n?as an object of type?int. When you use?n?in an assignment expression such as:

n = 3;

n?is an expression (a subexpression of the assignment expression) referring to an?intobject. The expression?n?is an lvalue.

Suppose you switch the left and right operands around:

3 = n;

Unless you're a former Fortran programmer, this is obviously a silly thing to do. The assignment is trying to change the value of an integer constant. Fortunately, C and C++ compilers reject it as an error. The basis for the rejection is that, although the assignment's left operand 3 is an expression, it's not an lvalue. It's an rvalue. It doesn't refer to an object; it just represents a value.

I don't know where the term rvalue comes from. Neither edition of the C Standard uses it, other than in a footnote stating "What is sometimes called 'rvalue' is in this standard described as the 'value of an expression.'"

The C++ Standard does use the term rvalue, defining it indirectly with this sentence: "Every expression is either an lvalue or an rvalue." So an rvalue is any expression that is not an lvalue.

Numeric literals, such as?3?and?3.14159, are rvalues. So are character literals, such as'a'. An identifier that refers to an object is an lvalue, but an identifier that names an enumeration constant is an rvalue. For example:

enum color { red, green, blue };
color c;
...
c = green;????// ok
blue = green;????// error

The second assignment is an error because?blue?is an rvalue.

Although you can't use an rvalue as an lvalue, you can use an lvalue as an rvalue. For example, given:

int m, n;

you can assign the value in?n?to the object designated by?m?using:

m = n;

This assignment uses the lvalue expression n as an rvalue. Strictly speaking, a compiler performs what the C++ Standard calls an?lvalue-to-rvalue conversion?to obtain the value stored in the object to which?n?refers.

Lvalues in other expressions
Although lvalues and rvalues got their names from their roles in assignment expressions, the concepts apply in all expressions, even those involving other built-in operators.

For example, both operands of the built-in binary operator?+?must be expressions. Obviously, those expressions must have suitable types. After conversions, both expressions must have the same arithmetic type, or one expression must have a pointer type and the other must have an integer type. But either operand can be either an lvalue or an rvalue. Thus, both?x + 2?and?2 + x?are valid expressions.

Although the operands of a binary?+?operator may be lvalues, the result is always an rvalue. For example, given integer objects?m?and?n:

m + 1 = n;

is an error. The + operator has higher precedence than the?=?operator. Thus, the assignment expression is equivalent to:

(m + 1) = n;????// error

which is an error because?m + 1?is an rvalue.

As another example, the unary?&?(address-of) operator requires an lvalue as its operand. That is,?&n?is a valid expression only if?n?is an lvalue. Thus, an expression such as?&3?is an error. Again,?3?does not refer to an object, so it's not addressable.

Although the unary?&?requires an lvalue as its operand, it's result is an rvalue. For example:

int n, *p;
...
p = &n;????// ok
&n = p;????// error: &n is an rvalue

In contrast to unary &, unary * produces an lvalue as its result. A non-null pointer p always points to an object, so *p is an lvalue. For example:

int a[N];
int *p = a;
...
*p = 3;???? // ok

Although the result is an lvalue, the operand can be an rvalue, as in:

*(p + 1) = 4;????// ok

Data storage for rvalue
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.

The assumption that rvalues do not refer to objects gives C and C++ compilers considerable freedom in generating code for rvalue expressions. Consider an assignment such as:

n = 1;

where?n?is an?int. A compiler might generate named data storage initialized with the value?1, as if?1?were an lvalue. It would then generate code to copy from that initialized storage to the storage allocated for?n. In assembly language, this might look like:

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

Many machines provide instructions with immediate operand addressing, in which the source operand can be part of the instruction rather than separate data. In assembly, this might look like:

mov #1, n

In this case, the rvalue?1?never appears as an object in the data space. Rather, it appears as part of an instruction in the code space.

On some machines, the fastest way to put the value?1?into an object is to clear it and then increment it, as in:

clr n
inc n

Clearing the object sets it to zero. Incrementing adds one. Yet data representing the values?0?and?1?appear nowhere in the object code.

More to come
Although it's true that rvalues in C do not refer to objects, it's not so in C++. In C++, rvalues of a class type do refer to objects, but they still aren't lvalues. Thus, everything I've said thus far about rvalues is true as long as we're not dealing with rvalues of a class type.

Although lvalues do designate objects, not all lvalues can appear as the left operand of an assignment. I'll pick up with this in my next column.

?

轉載于:https://www.cnblogs.com/csuftzzk/archive/2013/04/26/3045122.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/378514.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/378514.shtml
英文地址,請注明出處:http://en.pswp.cn/news/378514.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Opencv將處理后的視頻保存出現的問題

問題描述: 代碼運行過程中,imshow出來的每幀的效果圖是正確的,但是按照網上的方法保存下來卻是0kb,打開不了。 參考的網上的一些方法,均是失敗的,具體原因我也不清楚: 1、例如我這樣設置&#x…

Java Number shortValue()方法與示例

Number類shortValue()方法 (Number Class shortValue() method) shortValue() method is available in java.lang package. shortValue()方法在java.lang包中可用。 shortValue() method is used to return the value denoted by this Number object converted to type short (…

MATLAB可以打開gms文件嗎,gms文件擴展名,gms文件怎么打開?

.gms文件類型:Gesture and Motion Signal File擴展名為.gms的文件是一個數據文件。文件說明:Low-level, binary, minimal but generic format used to organize and store Gesture and Motion Signals in a flexible and optimized way; gesture-related…

黑白圖片顏色反轉并保存

將圖像的黑白顏色反轉并保存 import cv2 # opencv讀取圖像 img cv2.imread(rE:\Python-workspace\OpenCV\OpenCV/YY.png, 1) cv2.imshow(img, img) img_shape img.shape # 圖像大小(565, 650, 3) print(img_shape) h img_shape[0] w img_shape[1] # 彩色圖像轉換為灰度圖…

家貓WEB系統

現在只放源碼在些.為它寫應用很簡單有空整理文檔演示地址:jiamaocode.com/os/ 源碼:http://jiamaocode.com/ProCts/2011/04/14/1918/1918.html轉載于:https://www.cnblogs.com/jiamao/archive/2011/04/16/2018339.html

C# DataRow數組轉換為DataTable

public DataTable ToDataTable(DataRow[] rows) { if (rows null || rows.Length 0) return null; DataTable tmp rows[0].Table.Clone(); // 復制DataRow的表結構 foreach (DataRow row in rows) tmp.Rows.Add(row); // 將DataRow添加…

plesk 運行不了php,如何在Plesk中使用composer(使用其他版本的PHP運行Composer)

對于基于Plesk的服務器, composer的默認安裝將使用系統安裝的PHP版本, 而不使用Plesk所安裝的任何版本。盡管Composer至少需要PHP 5.3.2, 但是當你嘗試在需要特定版本PHP的項目中安裝依賴項時, 就會出現問題。例如, 如果你有一個至少需要PHP 7.2的項目, 并且系統的默認PHP安裝是…

Java Calendar hashCode()方法與示例

日歷類hashCode()方法 (Calendar Class hashCode() method) hashCode() method is available in java.util package. hashCode()方法在java.util包中可用。 hashCode() method is used to retrieve the hash code value of this Calendar. hashCode()方法用于檢索此Calendar的哈…

Error: Flash Download failed - Target DLL has been cancelled

博主聯系方式: QQ:1540984562 QQ交流群:892023501 群里會有往屆的smarters和電賽選手,群里也會不時分享一些有用的資料,有問題可以在群里多問問。 由于換了新電腦,keil重裝了下,然而之前的MCU的支持包沒有安裝,以及一些其他的問題,導致可以編譯但是不能將程序燒錄到單片…

設計一個較為合理的實驗方案來研究芳綸纖維的染色熱力學性能

請你設計一個較為合理的實驗方案來研究芳綸纖維的染色熱力學性能?包括吸附等溫線、親和力、染色熱和染色熵的測定,并指出實驗中應注意哪些事項來減少實驗誤差? 標準答案: 染色熱力學理論研究染色平衡問題。研究染色熱力學性能:首先研究選擇適宜的染料 吸附等溫線類型測定…

我也談委托與事件

雖然在博客園里面已經有很多關于C#委托和事件的文章,但是為了自己在學習的過程中,加深對委托的理解,我還是決定寫一下自己的心得體會。以備他日在回來復習。委托(delegate)是一個類,但是這個類在聲明的時候…

php錯誤攔截機制,php攔截異常怎么寫-PHP問題

php攔截異常可以通過PHP的錯誤、異常機制及其內建數set_exception_handler、set_error_handler、register_shutdown_function 來寫。首先我們定義錯誤攔截類,該類用于將錯誤、異常攔截下來,用我們自己定義的處理方式進行處理,該類放在文件名為…

智能車復工日記【4】:關于圖像的上下位機的調整問題總結

系列文章 【智能車Code review】—曲率計算、最小二乘法擬合 【智能車Code review】——坡道圖像與控制處理 【智能車Code review】——拐點的尋找 【智能車Code review】——小S與中S道路判斷 【智能車Code review】——環島的判定與補線操作 智能車復工日記【1】——菜單索引…

設計合理的實驗方案來研究陽離子改性棉織物與未改性棉的染色動力學性能

染色動力學性能研究染色的什么問題?設計合理的實驗方案來研究陽離子改性棉織物與未改性棉的染色動力學性能?并指出如何計算反映染色動力學的主要參數? 標準答案: 染色動力學研究染色速率問題。 為了研究陽離子改性棉纖維及未改性棉纖維對活性染料染色動力學性能,首先要測…

Java ArrayList toArray()方法及示例

ArrayList類的toArray()方法 (ArrayList Class toArray() method) Syntax: 句法: public Object[] toArray();public T[] toArray(T[] elements);toArray() method is available in java.util package. toArray()方法在java.util包中可用。 toArray() method is us…

小練習:新聞網站、SNS網站圖片播放器jQuery版

新聞網站和sns網站常見的圖片瀏覽器。直接看效果吧,效果預覽:http://u.vps168.com.cn/cos2004/photoView/, ie7、ie8、ff預覽正常,ie6和chrome預覽有一點小問題,研究中 作者:綠色花園 出處:htt…

SQL SERVER的鎖機制(四)——概述(各種事務隔離級別發生的影響)

SQL SERVER的鎖機制(一)——概述(鎖的種類與范圍) SQL SERVER的鎖機制(二)——概述(鎖的兼容性與可以鎖定的資源) 本文上接SQL SERVER的鎖機制(三)——概述&a…

如何測定拼色染液中,各染料在不同染色時間時,染液中殘留染料量及織物上吸附上染的染料量?

如何測定拼色染液中,各染料在不同染色時間時,染液中殘留染料量及織物上吸附上染的染料量? 標準答案: 通常依據各染料對特定波長光的吸光度具有加和性;吸光度值符合朗伯比爾定律,吸光度與濃度成正比;吸光度值分光光度計可以讀出;通過聯立方程,可以求出拼色各染料在染液中…

oracle云數據庫 免費的嗎,使用免費的Oracle云服務-創建ATP數據庫

前面我們講了在Oracle的云主機安裝數據庫,雖然現在安裝數據庫已經很簡單了,但是真正要在生產環境使用,還是需要進行很多配置和優化的,這通常需要專業的人員。而ATP(自治事務性數據庫服務)正是Oracle云提供的非常強大的數據庫云服務…

golang判斷結構體為空_如何在Golang中檢查結構是否為空?

golang判斷結構體為空The size of an empty structure is zero in Golang. Here, empty structure means, there is no field in the structure. 在Golang中, 空結構的大小為零。 在此, 空結構表示該結構中沒有字段。 Eg: 例如: Type struc…