2015-11-21 81 views
1

我知道int* ptr = (int*)buffer(其中bufferchar*)中斷 嚴格別名規則。通過引用訪問是否違反了嚴格的別名規則?

此語法int& ref = (int&)(*buffer)是否也違反規則?

I had一些SEGFAULT由於違反了嚴格的別名規則,而且這種語法已經消除了這種情況。雖然可能還是不正確的,是嗎?

+1

我知道引用遵循與這方面的指針相同的規則。然而,我不記得是否用int *替代了char *'(而不是反過來)是明確定義的。 –

+0

@ 5gon12eder編輯,謝謝 –

+0

如果緩衝區最初是一個int *轉換爲char *,然後返回到int *,這是用reinterpret_cast定義的 – galinette

回答

1

嚴格的別名規則意味着您不應該取消引用指向同一內存位置的不同類型的指針。

由於在您的發佈代碼中,您永遠不會取消引用,因此無法判斷這是否違反了規則而未查看所有代碼。

另外,對char *類型的別名是一個例外,並且不違反規則。這意味着您可以通過將其指針轉換爲char *並對其進行解引用來訪問包含任何類型的內存位置。

總之:

  • buffer如果點上含有一個int的存儲器位置,並且從int*轉化爲char*,這是有效的。但是,您應該對此使用reinterpret_cast
  • 如果緩衝區指向包含字符的內存位置,則解除引用int* ptr確實違反了規則。
  • 參考版本可能會遭受同樣的問題。但編譯器沒有義務阻止或警告您不要這樣做
  • 請勿使用C風格轉換,改爲使用reinterpret_cast,並閱讀關於哪些使用具有已定義的行爲的標準。
+0

正如我通過閱讀這個問題了解到的,允許使用char *來混淆T *反過來也不是。例如[這裏](http://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule)他們這樣說。 「但是,這不會以另一種方式工作:沒有假設你的結構將字符緩衝區別名」。又例如[這裏](http://stackoverflow.com/questions/32831329/strict-aliasing-and-writing-int-via-char)他們說,*((* int)p)= value;'違反嚴格的別名 –

+0

除非將int *轉換爲char *,否則返回int *。這是完全允許的,在這種情況下,您實際上將char *轉換爲int *並將其在您的代碼中的某處取消引用。 – galinette

2

這是不正確的(假設您將使用所述引用來訪問該值)。 §3.10 [basic.lval]¶的C++ 14標準(引用N4140)的10表示,(重點煤礦):

如果一個程序試圖通過其它一個glvalue訪問對象的存儲值比以下類型的行爲是未定義的一個:

  • 動態類型的對象,
  • 動態類型的對象的CV-合格版本,
  • 定義相似類型(在4。4)與對象的動態類型
  • 一種類型,它是與對象的動態類型對應的有符號或無符號類型,
  • 一種與cv限定版本對應的有符號或無符號類型對象的動態類型 ,
  • 集合或聯合類型,包括其元素中的上述類型之一或非靜態數據成員(包括遞歸地,子集合中的元素或非靜態數據成員 或包含的聯合),
  • 作爲對象的動態類型的(可能是cv合格的)基類類型的類型,
  • a charunsigned char類型。

無論您是否嘗試通過指針或引用進行訪問都無關緊要。對於類型爲char的存儲對象,沒有一個要點允許它允許以int的身份訪問它。

最後一個要點只說你可以別名其他類型爲char但反之亦然。這是合理的,因爲char是對齊要求最弱的最小可尋址單元。

如果需要,使用指針與使用引用相同,只不過您需要顯式取消引用才能訪問該值。

1

是的,它的確如此。

無論是C還是C++特例都通過指針訪問與其他訪問無關,嚴格的別名規則無論使用指針,引用還是任何其他左值都適用。

如果遇到麻煩,最簡單的解決方案是使用memcpy將內存位置複製到本地變量中 - 任何自尊的編譯器都會完全優化這種情況,並將其視爲別名提示(memcpy也是因爲聯合方法不如便攜式,所以最好比聯合更適合。

相關問題