的片段:
((int8_t) + (78));
是表達,一個取值78
,應用一元+
,然後投射該投擲它到int8_t
類型,前遠。這是沒有真正不同的法律表述:
42;
a + 1;
也計算表達式,然後扔掉的結果(儘管這些都將可能被優化掉的存在,如果編譯器可以告訴大家,有沒有副作用)。
這些「裸體」表達式在C語言中是完全有效的,並且通常僅當它們有副作用時纔有用,例如i++
,它計算i
並將其丟棄並帶來副作用,即增加值。
你應該使用宏觀的方法是沿的線條更:
int8_t varname = INT8_C (somevalue);
的原因看似多餘的一元+
操作員可在標準中找到。引用C99 6.5.3.3 Unary arithmetic operators /1
:
一元+或 - 運算符的操作數應具有算術類型;
而且,在6.2.5 Types, /18
:
整數和浮點類型統稱爲算術類型。
換句話說,一元+
阻止您使用宏中的所有其他數據類型,例如指針,複數或結構。
最後,原因你:
signed char + 78;
片段不工作是因爲它是不一樣的事情。這個人開始聲明signed char
類型的變量,但是當它到達+
時,扼流器因爲不是合法的變量名稱。爲了使其等同於你的工作片段,您可以使用:
(signed char) + 78;
這是價值+78
的鑄造鍵入signed char
。
而且,按C99 7.8.14 Macros for integer constants /2
,你也應該小心那些宏使用非常量,他們不能保證工作:
在這些宏的任何實例的參數應該是未定義的整數常量(如6.4.4.1中定義的 ),其值不超過相應類型的限制。
6.4.4.1
簡單地規定了不同的整數格式(十進制/八進制/十六進制)與各種後綴(U
,UL
,ULL
,L
,LL
和小寫當量,取決於類型)。底線是他們必須是常量而不是變量。
例如,glibc
有:
# define INT8_C(c) c
# define INT16_C(c) c
# define INT32_C(c) c
# if __WORDSIZE == 64
# define INT64_C(c) C## L
# else
# define INT64_C(c) C## LL
# endif
,這將使你的INT8_C
宏工作正常,但文本INT64_C(val)
將事先加工成任何valL
或valLL
,這兩者都不你會想。
應該指出,這個'INT8_C'的定義是錯誤的:7.18。4段落3:「每次調用其中一個宏(注意:指的是INTN_C)應擴展爲一個整型常量表達式**,適用於'#if'預處理指令。**」該類型轉換不起作用在預處理器指令中,因爲在預處理期間不存在類型(因此類型轉換)。你在使用什麼編譯器/平臺?你應該考慮提交關於這個的錯誤報告。 –
@ChrisLutz:在C99中有效;在納入N1256的技術勘誤1中變得無效。這是對[DR#209]的迴應(http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_209.htm)。 –
@凱瑟湯普森 - 啊。我有一份TC2的副本,直到最近還沒有真正意識到技術勘誤。 –