回答
您已定義未命名的struct
實際上table
是對象不是struct
的名稱。
所以,如果你有這樣的聲明
typedef struct
{
uint64_t offsets[0];
} table;
或者,
struct table
{
uint64_t offsets[0];
} table;
然後,這就是所謂的可變長度數組(稱爲結構破解)。
有限制,它應該是結構的最後一個成員。
您發佈的代碼是正式失效。正式的C語言不支持尺寸爲0
的數組。
一些編譯器(使用鬆散/遺留錯誤檢查)允許在結構的結尾處有一個大小爲零的數組,它有時用於實現所謂的"struct hack"。 (更好的方法是使用大小爲1的尾部數組。)但是,您的聲明不提供該用途。 「Struct hack」需要一個命名的結構類型,而實際的對象必須動態分配。在你的情況下,結構類型是未命名的,變量table
是非動態定義的。所以,「struct hack」在這裏是沒有問題的,假設你正確地重現了代碼。
因此,即使它編譯,最終變量table
包含沒有可用的數據。該變量的唯一用途(如果聲明爲靜態存儲持續時間)是通過&table
表達式(指向「匿名結構」類型的指針)產生唯一的地址常量。
一種方式把你的宣言到的東西更接近「結構黑客」是在它前面加上一個typedef
typedef struct
{
uint64_t offsets[0];
} table;
然而,「人類產生的」結構聲明爲「結構黑客「通常會在靈活數組聲明之前包含其他數據字段(沒有它們就沒有必要在普通數組上選擇」struct hack「)。
在Linux內核中,我們可以將問題縮小到GCC可以處理的問題。 – Potatoswatter
這是一種技巧,可以讓您將任意大小的內存塊轉換爲您的指針類型,並使最後一個數組成員變爲可變長度數組。雖然可能不是標準的,但這是可行的,因爲C數組不是邊界檢查的。
這裏是一個非常簡單的例子來展示它:
typedef struct Foo
{
int count;
int array[0];
} Foo;
Foo* foo = (Foo*)malloc(sizeof(Foo) + 5 * sizeof(int));
foo->count = 5;
然後,您可以使用count
域得知該Foo*
中有效元素的數量。如上所述,由於C數組未經過邊界檢查,因此編譯器和運行庫在您嘗試讀取或寫入數據時都不會捕獲大小爲0的大小爲foo->array
。
- 1. 使用NUnit測試構造
- 2. 測試是否a&b == 0
- 3. 「struct a a1 = {0};」不同於「struct a a2 = {5};」爲什麼?
- 4. 構造A HREF =使用XSLT
- 5. 測試構造使用模擬
- 6. C++ struct構造函數
- 7. 測試構造ARGS
- 8. JUnit測試構造函數測試
- 9. Junit測試構造函數
- 10. Java測試驗證構造
- 11. 測試構造函數
- 12. 測試「創造」使用RSpec
- 13. 使用指針訪問結構struct struct
- 14. C++ Struct失敗POD測試
- 15. 如何單元測試結構構造
- 16. 使用struct構造函數的怪異行爲
- 17. C++ struct構造函數錯誤
- 18. typedef struct error:expected a';'
- 19. AngularJS單元測試:構造函數測試:Windows Azure調用Api
- 20. 單元測試類構造函數
- 21. A/B在Google Play中構建測試
- 22. Powemockito構造函數測試問題
- 23. 死亡測試構造與GoogleTest
- 24. 構造函數的單元測試
- 25. 如何測試在一個構造方法調用使用RSpec
- 26. 從基類構造子類struct
- 27. 清零構造函數中的struct
- 28. 使用新澤西測試框架JerseyTest構造
- 29. 如何在Python中使用這個bash測試構造?
- 30. 編組Struct結構的數組構造結構
這與以下情況有何不同:'struct {uint64_t offset; }表;' – Shraddha
除了一些特定於實現的東西外,您現在沒有什麼實際用途。它類似於經典的「struct hack」,但是您提供的聲明不能用於此目的。 – AnT
它的不同之處在於'uint64_t offset'會引入一個'uint64_t'類型的字段。同時,一個大小爲'0'的數組(如果它編譯在你的編譯器中)根本不會引入數據。你的變量'table'是空的。它本身的大小爲'0',這就是爲什麼我說它沒有實際用途。實際上,它唯一使用的就是在內存中佔用一些唯一的地址。 – AnT