由於取消引用nullptr
(NULL
)是一個未定義的行爲都在C
和C++
,我想知道如果表達式&(*ptr)
是有效的,如果是PTR nullptr
(NULL
)。C/C++ nullptr解除引用
如果它也是一個未定義的行爲,鏈接的答案中的OFFSETOF宏如何工作?
我一直認爲ptr->field
是(*ptr).field
速記我想回答我的問題是在C和C++類似。
由於取消引用nullptr
(NULL
)是一個未定義的行爲都在C
和C++
,我想知道如果表達式&(*ptr)
是有效的,如果是PTR nullptr
(NULL
)。C/C++ nullptr解除引用
如果它也是一個未定義的行爲,鏈接的答案中的OFFSETOF宏如何工作?
我一直認爲ptr->field
是(*ptr).field
速記我想回答我的問題是在C和C++類似。
TL; DR &(*(char*)0)
是明確定義的。
C++標準本身並沒有說空指針的間接有UB。當前草案標準,[expr.unary.op]
一元*運算符執行間接:表達到其所施加應的指針的對象類型,或指向函數類型,其結果是一個左值指的是表達指向的對象或函數。如果表達式的類型是「指向T的指針」,則結果的類型是「T」。 [snip]
一元運算符&的結果是一個指向其操作數的指針。操作數應該是一個左值或一個合格的ID。 [剪斷]
沒有UB除非間接表達的左值被轉換爲右值。
C標準更爲明確。 C11標準草案§6.5.3.2
- 一元&操作者產生其操作數的地址。如果操作數的類型爲「type」,則結果的類型爲「指向類型的指針」。 如果操作數是一元*運算符的結果,那麼對運算符和運算符都不進行評估,結果就好像兩個都被省略了一樣,除了運算符上的約束仍然適用並且結果不是左值。類似地,如果操作數是[]運算符的結果,那麼運算符[&]和[]所隱含的一元運算符*都不會被求值,結果就好像運算符已被移除並且[]運算符已被更改到+運營商。否則,結果是指向由操作數指定的對象或函數的指針。
如果它也是一個未定義的行爲,請問
offsetof
工作?
優選使用the standard offsetof
macro。自制版本會導致編譯器警告。此外:
offsetof
需要工作如上規定,即使一元operator&
超載爲所涉及的任何類型的。這不能在標準C++中實現,需要編譯器支持。
offsetof
是built-in function in gcc。
OP指的是鏈接中的宏:#define OFFSETOF(type,field)((unsigned long)&(((type *)0) - > field)) –
@Byteventurer沒有理由使用自制的'偏移量「,它會導致編譯器警告。使用標準['offsetof'](http://en.cppreference.com/w/cpp/types/offsetof)。 –
我沒有宣傳宏的使用,我正在解釋OP在提問時所指的是什麼...... –
C11草案標準n1570:* 6.5.3.2地址和間接運算符3 一元&運算符產生其操作數的地址。如果操作數的類型爲''type'',則 結果的類型爲''指向類型''。如果操作數是一元操作符 的結果,那麼操作符和&運算符都不會被評估,結果就好像兩個都省略了 ,除了運算符上的約束仍然適用並且結果不是左值。 * – EOF
我將此標記爲重複項,但請務必閱讀C++答案下的討論以及[本討論](http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active .html#232),因爲這在C++標準中並不那麼明確。 – TartanLlama
我懷疑這是重複的,因爲OP詢問「如果解除引用'nullptr'是UB工作的方式有多糟糕」 – Slava