為什麼GCC會把0xBE-0x33解釋為浮點數?
今天在寫程序的時候,寫下了類似這樣的語句:
uint8_t data=0xBE-0x33;我的本意當然是0xBE減去0x33,結果GCC當成了浮點數(E:科學計數法),然後給我報了一個錯誤:
invalid suffix "-0x33" on integer constant除了加括弧變成(0xBE)-0x33,還有什麼方法解決呢
終於反應過來了,編譯器是把它當成了(0xB) * 10 ^ (-0x33) ……
類似問題:r = *p/*q; 這個語句有什麼毛病?
- 兩邊加上空格,寫成 0xBE - 0x33,這樣不僅能夠避免題中的問題,代碼讀起來也比不加空格清晰很多。
C++17 的十六進位浮點 floating point literal- 左右加空格就行了
只有我一個人覺得造成這麼大代碼兼容性破壞的語法,居然還能留著不刪很不可思議么(
更新
去floating point literal上的自帶編譯插件做了點實驗。0x1e2 //482
0x1p-2 //0.25
0x1-0x2 //-1
0x1f+2 //正常,33
main.cpp:4:16: error: unable to find numeric literal operator "operator""+1"
std::cout &<&< 0x1e+1 &<&< "
";
^~~~~~
0x1e +1 //31
main.cpp:4:16: error: unable to find numeric literal operator "operator""-0x2"
std::cout &<&< 0x1e-0x2 &<&< "
";
^~~~~~~~
main.cpp:4:16: error: unable to find numeric literal operator "operator""-2"
std::cout &<&< 0x1e-2 &<&< "
";
^~~~~~
0x1ef+1 //496
main.cpp:4:16: error: unable to find numeric literal operator "operator""+1"
std::cout &<&< 0x1ee+1 &<&< "
";
^~~~~~~
有點不懂這個詞法……在0x後面對結尾e還有區別對待咯?
要養成雙目運算符左右加空格的習慣這是好習慣
GCC並沒有把0xBE-0x33解釋為浮點數
[lex.ppnumber]:
pp-number:
digit
. digit
pp-number digit
pp-number identifier-nondigit
pp-number 』 digit
pp-number 』 nondigit
pp-number e sign
pp-number E sign
pp-number p sign
pp-number P sign
pp-number .
Preprocessing number tokens lexically include all integer literal
tokens ([lex.icon]) and all floating literal
tokens ([lex.fcon]).A preprocessing number does not have a type or a value; it acquires both
after a successful conversion to an integer literal token or a floating literal
token.
pp-number 屬於 proprocessing token 但不屬於 token
0xBE-0x33 符合 pp-number 的語法,但不符合任何一種 token 的語法[lex.pptoken]:
Each preprocessing token that is converted to a token ([lex.token])
shall have the lexical form of a keyword, an identifier, a literal, an
operator, or a punctuator.
轉換為 token([lex.token])的每個 preprocessing token 應具有關鍵字,標識符,文字,操作符或標點符號的詞法形式。
0xBE-0x33不滿足這一點。
違反 shall 就表示 program is ill-formed, diagnostics required,用人話說就是編譯錯誤
類似0xBE-0x33的例子 —— 0xe+foo(這一段還是在[lex.pptoken]):
[ Example: The program fragment 0xe+foo is parsed as a
preprocessing number token (one that is not a valid floating or integer
literal token), even though a parse as three preprocessing tokens
0xe, +, and foo might produce a valid expression (for example,
if foo were a macro defined as 1). Similarly, the
program fragment 1E1 is parsed as a preprocessing number (one
that is a valid floating literal token), whether or not E is a
macro name. — end example ]
Visual Studio會在你按下;的時候猛插空格,然後什麼事情都沒有了。如果你是想讓你的程序運行在Linux上面的話,你可以使用Visual GDB來從Windows來一鍵(F5)編譯部署調試進Linux地虛擬機里,體驗就像運行一個本地程序一樣。
加空格大法好
運算是一定要加空格 不僅是習慣也是為了從一開始就避免錯誤 不然 x+++++y 不是要了compiler 老命么
推薦閱讀:
※c語言中指針指向的非指針變數不能使用++或--嗎?
※指針是如何記住步長的?
※C中有沒有將一個函數轉變為另一個函數的函數(例如求導運算)?
※函數實現的時候,將函數返回值另起一行書寫,這是一種好的代碼書寫風格么?
※C語言中volatile修飾符的作用?