[英]Could this use of malloc lead to an “optional” struct field?
我正在實現一個結構,我需要(在運行時)有一個可選字段。
所以我想到了這個:
//...
#include <stdlib.h>
struct test {
int x; // Must be
int y; // Optional (Must be the last field..(?))
};
int main(int argc, char **argv) {
// With the optional field
struct test *a = malloc(sizeof(*a));
a->x = 11;
a->y = 55;
// Without the optional field
struct test *b = malloc(sizeof(*b) - sizeof(int));
b->x = 22;
// ...
free(a);
free(b);
return 0;
}
這段代碼可以按我的要求做嗎?
可能添加一個位字段來檢查是否有可選字段。
此外,如果建議的解決方案有效,如果這是針對多個項目(> 100000)的列表實施的,那么保存 memory 會更好嗎?
這段代碼可以按我的要求做嗎?
好吧,它可以,但你不能依賴它。 不要這樣做; 這不是編寫正確程序的方法。
當你寫b->x = 22;
,編譯器有權表現得好像在b
處有一個完整的struct test
。 您可能會想,“我只是將 22 放入成員x
的字節中”,但編譯器可能會使用“存儲 8 個字節”指令:
b->x = 22;
,並且它知道y
尚未設置,因此允許它具有任何值。 因此,編譯器不會使用低效的寫入四字節序列,而是生成一個八字節存儲,將 22 放入b->x
並將 0 放入b->y
。 然后這會失敗,因為編譯器剛剛將 0 寫入 memory 可能正在用於其他用途,因為它不是您為b
分配的空間的一部分。
“如果你對編譯器撒謊,它就會報仇雪恨。” — 亨利·斯賓塞
What you're attempting doesn't conform to the C standard because you're attempting to use an object of type struct test
that doesn't have enough memory allocated for it, even though you're only accessing the fields for which memory was分配。 它可能有效,但你不能依賴它。
您可以做的是使用靈活的數組成員:
struct test {
int x;
int y[];
};
在這樣的結構中, sizeof(struct test)
不包括最后一個成員。 您可以通過為結構分配空間以及所需的最后一個成員的盡可能多的數組元素來使用這樣的結構。 例如:
struct test *b = malloc(sizeof(*b) + sizeof(int));
b->x = 1;
b->y[0] = 2;
您需要使用數組索引來訪問最后一個成員,但這是一種以符合標准的方式執行所需操作的方法。
然后,如果您不想要最后一個成員,請執行以下操作:
struct test *b = malloc(sizeof(*b));
b->x = 1;
我認為您提出的解決方案很危險。 使用兩種不同的結構:
struct test_x {
int x;
};
struct test_xy {
int x;
int y;
};
要么有兩個 arrays 要么將 void * 與鑒別器(例如標記指針)一起存儲到其中一個。 另一個選項是對可選元素使用指針,但 sizeof(int *) 至少在我的盒子上與 sizeof(int) 相同,這樣只會使事情變大。
如果所有 y 成員都是可選的,請考慮列布局,或者您可以對數據進行排序,以便所有 xy 元素排在第一位:
struct test_column {
int *x;
int *y;
};
struct test_column t = {
.x = malloc(100000 * sizeof(int)),
.y = 0
它對您沒有幫助,但聯合是兩個結構共享 memory 的標准方式,因此每個元素的大小是 max(sizeof(test_xy), sizeof(test_x)) 而不是 sizeof(test_xy) + sizeof(test_x)。
最后,考慮壓縮,特別是如果您使用 test_column 格式。
我 state 我不是 C 方面的專家,但我正在研究它。
我正在實現一個結構,我需要(在運行時)有一個可選字段。
所以我想到了這個:
//...
#include <stdlib.h>
struct test {
int x; // Must be
int y; // Optional (Must be the last field..(?))
};
int main(int argc, char **argv) {
// With the optional field
struct test *a = malloc(sizeof(*a));
a->x = 11;
a->y = 55;
// Without the optional field
struct test *b = malloc(sizeof(*b) - sizeof(int));
b->x = 22;
// ...
free(a);
free(b);
return 0;
}
這段代碼可以按我的要求做嗎?
可能添加一個位字段來檢查是否有可選字段...
此外,如果建議的解決方案有效,如果這是針對多個項目(> 100000)的列表實施的,那么保存 memory 會更好嗎?
謝謝大家,提前。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.