推 diabloevagto:還是分開寫的好 02/14 23:52
推 EntHeEnd:推 02/15 01:01
→ purincess:我剛剛跟我朋友說 my python is better than my c++ 02/15 01:27
→ purincess:and my javascript is better than my c 在此得到印證(? 02/15 01:27
→ scwg: (a = 55) = 66 踩到 double assignment, a 要是多少都可吧 02/15 03:25
→ scwg: grammar 那邊的分析是對的, 不過 一、不當左值用 一樣有 02/15 03:33
→ scwg: multiple assignment 的問題 02/15 03:33
感謝。
依據 C++03 在 5.17 Assignment operators 的內文中說:
The result of the assignment operation is the value stored in the
left operand after the assignment has taken place;
the result is an lvalue.
所以 (a = 55) = 66 這樣的運算,在 C++ 環境下,a 應該可以得到 66。
同時,在 C 的環境下,總是會變成 invalid lvalue in assignment 編譯錯誤。
不知道這樣理解對嗎?謝謝。
推 cole945:推 ``世界上根本就沒有 "運算子優先權表"'' 這句.. 02/15 05:00
※ 編輯: purpose 來自: 124.8.132.109 (02/15 06:07)
推 DEATHX:世界上根本就沒有 "運算子優先權表" +1 02/15 08:59
推 Favonia:這問題超麻煩... orz 02/15 19:04
推 dSnAil:世界上根本就沒有 "運算子優先權表"+1 02/15 21:03
推 xxxx9659:記起來了 ?:運算式 不當左值使用 02/17 19:42
==============================================================================
請先詳細讀完上文,以下回應開始:
一點淺見與各位分享,若有錯誤請指正,並請海涵,謝謝。
先講結論:
(一)在 C99 中「=」的結果不是 lvalue,但 C++03 中卻是
lvalue,此結果導致「?:」運算子的傳回值也是不同的。
(二)若「A?B:C」中的 C 中含有「=」的時候,GCC C++
Compiler 會將整個敘述視為是 assignment-expression,而不是
範圍較小的 conditional-expression,也就是說「A?B:C」
如果是「1 ? varA = 1 : varB = 2 ;」,其中的敘述C是
「varB = 2」,而不是「varB」,但我個人認為這不符合程設邏輯
,如果有兩種選擇的話,編譯器應當選擇較小範圍感覺上較合理,
更何況「?:」運算子的順序還高過「=」運算子呢,這不知道算不
算 GCC 的 Bug?;另一方面,GCC C Compiler 則將
「1 ? varA = 1 : varB = 2 ;」中的敘述C視為「varB」,因此
整個敘述變成了先執行「?:」傳回了一個「不是lvalue」的值(注
意在 C++ 中傳回 lvalue!),然後將此值經由「=」賦予 2,然
而又因為此值不是 lvalue 因此編譯器回報錯誤(lvalue
required as left operand of assignment)。
<註>在 Wikipedia (2013/02/26) 的 Operators in C and C++ 條目提到:
----------------------------------------------------------------------
The binding of operators in C and C++ is specified (in the
corresponding Standards) by a factored language grammar, rather
than a precedence table. This creates some subtle conflicts.
For example, in C, the syntax for a conditional expression is:
logical-OR-expression ? expression : conditional-expression
while in C++ it is:
logical-OR-expression ? expression : assignment-expression
Hence, the expression:
e = a < d ? a++ : a = d
is parsed differently in the two languages.
In C, this expression is a syntax error, but many compilers
parse it as:
e = ((a < d ? a++ : a) = d)
which is a semantic error, since the result of the
conditional-expression (which might be a++) is not an lvalue.
In C++, it is parsed as:
e = (a < d ? a++ : (a = d))
which is a valid expression.
----------------------------------------------------------------------
(三)誠如 purpose 君所言,C++03 中提到「The precedence of
operators is not directly specified, but it can be derived
from the syntax.」,我想這就是造就第二點的原因。例如
「i=0, i++, i++;」,值得注意的是「++」運算子的順序高於「,」
運算子以及「=」運算子,但根據 C++03 的說法 i 應當是 2!
(四)個人認為在寫程式的時候,應當不要使用如此容易讓人疑惑,
甚至可能在某些實作環境也可能讓編譯器疑惑的語法;不才亦認為如
此作法並不會讓程式執行起來更快,因為編譯器的工作是將程式語言
敘述轉成機器碼,或許語法寫得複雜難懂,但結果卻跟簡單語法一樣
(何況現今許多編譯器都已經號稱有最佳化的功能了),所以這樣做
可說是得不償失,減少了移植性和可讀性、維護性。
(五)希望各位在討論這個主題的時候可以列出編譯的環境,因為在
各種實做環境說不定結果是不同的。
(六)以下提供兩個檔案,是我用以實驗的程式,請各位參考;註解
內是利用 GCC 4.7.2 編譯並執行的結果,並請有其他環境(MSVC,
IntelCompiler)的朋友提供執行結果,謝謝。
============ CODE START ============
/* ---------------------------------------------------------
* Description: the Usage of '?:' Operators ( C++ version )
* Author: ShaDer(ptt.cc) (aka. ShaD)
* License: General Public License version 2 (GPLv2)
* Compiler: C++ (gcc-4.7.2)
----------------------------------------------------------*/
#include <iostream>
using namespace std;
int main() {
int TelNum = +886-2-3366-3366; //-- This is NOT my number :)
cout << TelNum << "\n"; //-- output test: -5848
int a, b, c;
/*
a = 9, b = 10;
1 ? a = 99 : b = 1010;
cout << a << "\n"; // 99
cout << b << "\n"; // 10
*/
/*
a = 3, b = 4;
(1 ? a = 33 : b) = 44;
cout << a << "\n"; // 44(!!!)
cout << b << "\n"; // 4
*/
/*
a = 5, b = 6;
(1) ? (a = 55) : (b) = 66;
cout << a << "\n"; // 55
cout << b << "\n"; // 6
*/
/*
a = 7, b = 8;
1 ? (a = 77) : b = 88;
cout << a << "\n"; // 77
cout << b << "\n"; // 8
*/
/*
a = 5, b = 6, c = 1;
1 ? a = 55 : b = c++;
cout << a << "\n"; // 55
cout << b << "\n"; // 6
cout << c << "\n"; // 1
a = 5, b = 6, c = 1;
1 ? a = 55 : b = ++c;
cout << a << "\n"; // 55
cout << b << "\n"; // 6
cout << c << "\n"; // 1
*/
/*
a = 5, b = 6, c = 1;
(1 ? a = 55 : b) = (c++);
cout << a << "\n"; // 1
cout << b << "\n"; // 6
cout << c << "\n"; // 2
*/
/*
a = 5, b = 6, c = 1;
(1 ? a = 55 : b++) = (c++);
// Error: lvalue required as left operand of assignment
cout << a << "\n";
cout << b << "\n";
cout << c << "\n";
*/
/*
a = 5, b = 6, c = 1;
(1 ? a = 55 : (b++)) = (c++);
// Error: lvalue required as left operand of assignment
cout << a << "\n";
cout << b << "\n";
cout << c << "\n";
*/
return 0;
}
============= CODE END =============
============ CODE START ============
/* ---------------------------------------------------------
* Description: the Usage of '?:' Operators ( C version )
* Author: ShaDer(ptt.cc) (aka. ShaD)
* License: General Public License version 2 (GPLv2)
* Compiler: C/C++ (gcc-4.7.2)
----------------------------------------------------------*/
#include <stdio.h>
int main(void) {
int a, b;
a = 1, b = 2;
1 ? (a = 11) : (b = 22) ;
printf("a=%d, b=%d\n", a, b);
/* C: a = 11, b = 2 */
/* C++: a = 11, b = 2 */
a = 3, b = 4;
1 ? a = 33 : (b = 44) ;
printf("a=%d, b=%d\n", a, b);
/* C: a = 33, b = 4 */
/* C++: a = 33, b = 4 */
/**********************************************************************
| 敘述『(1 ? (a = 55) : b ) = 66;』不符合 C99 規則,但 C++03 則通過, |
| 原因應來自 assignment operators 在 C++03 的結果是 lvalue,但在 C99 |
| 卻不是 lvalue,此結果導致「?:」運算子的傳回值也是不同的。 |
**********************************************************************/
a = 5, b = 6;
(1 ? a = 55 : b ) = 66 ;
printf("a=%d, b=%d\n", a, b);
/* C: ERROR: lvalue required as left operand of assignment */
/* C++: a = 66, b = 6 */
a = 7, b = 8;
1 ? (a = 77) : b = 88 ;
printf("a=%d, b=%d\n", a, b);
/* C: ERROR: lvalue required as left operand of assignment */
/* C++: a = 77, b = 8 */
a = 9, b = 10;
1 ? a = 99 : b = 1010 ;
printf("a=%d, b=%d\n", a, b);
/* C: ERROR: lvalue required as left operand of assignment */
/* C++: a = 99, b = 10 */
return 0;
}
============= CODE END =============
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 111.251.73.137
※ 編輯: ShaDer 來自: 111.251.73.137 (02/26 11:02)
※ 編輯: ShaDer 來自: 111.251.73.137 (02/26 11:10)
※ 編輯: ShaDer 來自: 111.251.73.137 (02/26 11:15)
※ 編輯: ShaDer 來自: 111.251.73.137 (02/26 11:39)
→ uranusjr:?: 的用途是簡化語法, 如果還寫得落落長就失去意義了 02/26 11:47
推 xxxx9659:請問各位 這樣寫在任何的 C 或是 C++ 都是對的嗎? 03/01 21:38
→ xxxx9659:(2 > 1 ? varA : varB ) = 20; 03/01 21:38
→ xxxx9659:如果有再哪一版的 C / C++ 可能會錯那 我就不這樣寫了 03/01 21:38
→ purpose:當左值就是這麼難用 就是這麼難用 就是這麼難用 03/01 21:50
推 xxxx9659:大大不要激動XD 保險起見不要用就是了 03/01 22:00