2015-01-03 52 views
0

考慮內存佈局

Foo data[]={{...},{...},{...}}; 
Foo data_end={...}; 

如果結束標記在陣列之後所定義,是它保證

&data[3]==&data_end 

我不想具有計數在數據元素的數量手動。

它恰好在gdb中沒有任何優化選項,但在使用它之前,我需要知道編譯器不能移動data_end。如果可以,我該怎麼做。

+0

僅通過元件的數量劃分的大小或添加恆定,並把它在[] – paulm

回答

1

不。這不是一個可靠的假設,編譯器將變量按任何順序或任何對齊方式放置。對齊的變量之間可能存在差距,我已經看到了按字母順序排列變量的編譯器。

如果你想知道指向元素的指針是而不是你需要知道數組元素的個數。

#define _dimof(a) (sizeof(a)/sizeof(a[0])) 
Foo data[] = ... ; 
// The type of the variable has been changed. 
Foo* data_end = &data[_dimof(data)]; 

您可以刪除此段落,因爲它已被添加以修復代碼中的語法錯誤。

+0

在這種情況下,這將會佔用更少的空間,因爲'sizeof(Foo)== 3 * sizeof(void *)' – user877329

+0

@ user877329這取決於Foo的定義什麼沒有在問題中顯示。更值得注意的是,你可以放棄虛擬變量,只要你想要的地址。 – harper

4

您不僅要求什麼是不能保證的,但此外,C++ 03兼容的實現必須確保&data[3] != &data_end

5.10平等運營商[expr.eq]

1 ...相同類型的兩個指針比較相等的當且僅當它們都是空的,都指向相同的對象或函數,或者兩者都指向相同數組的末尾。

在C++ 11,它是一個小更復雜:

相同類型的

兩個指針比較相等當且僅當它們都爲null,都指向相同的功能,或兩者代表相同的地址(3.9.2)。

3.9.2注意事項:

...如果T類型的對象位於一個地址A,類型的指針CVT*其值地址A據說指向該對象,而不管價值是如何獲得的。 [注意:例如,數組末尾的地址(5.7)將被視爲指向可能位於該地址的數組元素類型的不相關對象。 ...末端注]

因此,新標準允許相符實現可能會在比較產量真;仍然沒有保證。

如果你需要計算一個數組的元素個數,使用下面的股票宏:

#define countof(ARR) (sizeof (ARR)/sizeof *(ARR)) 

或者,如果你不喜歡宏,請使用以下功能:

template<class T, std::size_t N> 
constexpr std::size_t countof(T (&)[N]) 
{ 
    return N; 
} 

但是,後一個選項需要您的編譯器支持constexpr關鍵字與前者完全等效。

+0

我低估了你,因爲你提出了這個宏,因爲它是一個可行的選項。 – Puppy

+1

@Puppy,其實宏*是一個可行的選擇。這可能有兩個原因:1.我們中的一些人仍然需要處理不完全符合C++ 11並且不支持'constexpr'關鍵字的編譯器。如果沒有'constexpr',你不能執行以下操作:'int a [] = {...}; int b [countof(a)];'2.我們中的一些人編寫了希望包含在C和C++編譯單元中的頭文件。在這種情況下,您可能會注意到,模板根本無法使用。 – ach

+0

OP沒有這樣的要求。另外,如果他將自己的數組定義爲'boost :: array',那麼首先就沒有問題,因爲您可以直接請求大小。他提到沒有要求結果是一個不變的表達。簡而言之,您發佈的蹩腳代碼適用於不適用於此的要求。 – Puppy

0

不,它是不可靠的,在C++ 11,只是做

for (/* const */ Foo& foo : data) { 
    // stuff with foo. 
}