為什麼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修飾符的作用?

TAG:計算機 | C編程語言 | GCC |