有沒有一種很好的方式來結合C99的指定初始值設定項和malloc
的結果?在C99 +中組合指定的初始值設定項和malloc?
下似乎有不必要的重複:
typedef struct {
int a, b, c;
} Type;
Type *t = malloc(sizeof *t);
*t = (Type) {
.a = 2,
.b = 3,
.c = 5,
};
可以使用Type
,並且*t
從上面的代碼被刪除?
有沒有一種很好的方式來結合C99的指定初始值設定項和malloc
的結果?在C99 +中組合指定的初始值設定項和malloc?
下似乎有不必要的重複:
typedef struct {
int a, b, c;
} Type;
Type *t = malloc(sizeof *t);
*t = (Type) {
.a = 2,
.b = 3,
.c = 5,
};
可以使用Type
,並且*t
從上面的代碼被刪除?
既然你問了;)C中有一個工具可以避免顯式重複的代碼宏。這就是說我沒有看到一種不重複至少這種類型的名稱的方法。但在C++他們不能要麼,所以C是至少一樣好:)
我看到的最簡單的就是
#define DESIGNATE_NEW(T) \
memcpy(malloc(sizeof(T)), \
&(T const){ __VA_ARGS__ }, \
sizeof(T))
這將使
Type *t = DESIGNATE_NEW(Type,
.a = 2,
.b = 3,
.c = 5,
);
這有幾個優點。
0
的浮法類型或指針非 標準表示架構。注意:觀察宏中的const
,如果編譯器確定這是相關的,則允許摺疊複合文本的多個實例。另外,還有一種方法可以使用指示符列表可選的變體,請參閱下面的P99。
缺點是memcpy
和我會更快樂與任務。其次,在使用結果之前,沒有檢查malloc
的失敗,但可能會遇到一些奇怪的情況,以使代碼良好地退出。
在P99我採取了稍微不同的方式。在那裏,我們總是有一類的初始化函數,像
inline
Type* Type_init(Type* t, int a, int b, int c) {
if (t) {
*t = (Type const){ .a = a, .b = b, .c = c };
}
return t;
}
其受宏觀神奇,可向爲a
,b
和c
提供默認參數,如果省略它們。然後你可以簡單地使用類似於
Type *t = P99_NEW(Type, 1, 2, 3);
在你的應用程序代碼。這比較好,因爲它避免了在malloc
的調用失敗時導致指針無效。另一方面,這重新向初始化者發出一個命令,所以也不完美。
您的'DESIGNATE_NEW'宏最接近成爲一個慣用的解決方案。 –
不,這是使用指定初始值設定項的唯一方法。沒有(類型){},編譯器不知道如何驗證內容。
您可以使用可變宏。我不會說這是一個好主意,但它的工作原理:
#include <stdlib.h>
#include <stdio.h>
#define CREATE(type, ptr, ...) \
type *ptr = malloc(sizeof *ptr); \
if (ptr) *ptr = (type){__VA_ARGS__}
int main(void)
{
typedef struct {
int a, b, c;
} Type;
CREATE(Type, t, .a = 2, .b = 3, .c = 5);
printf("t->a = %d, t->b = %d, t->c = %d\n", t->a, t->b, t->c);
return 0;
}
請注意,我無法使用通常的do { ... } while (0)
宏定義技巧(這將創建一個新的範圍,t
將不可見),所以你必須小心使用它的上下文。
就我個人而言,我覺得我對不必要的重複感到高興。
如果可以,如果'malloc'返回'NULL'會發生什麼? – detly
看起來像你真的想要C++。 –
有趣的問題,但我不認爲有任何好的答案。就個人而言,我只會使用'calloc',接着是't-> a = 2; t-> b = 3;'...('calloc'就在那裏,以防你想離開任何成員,所以如果你知道你會明確地設置它們,你也可以使用'malloc') –