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
ますか?
以下は不必要な重複があるようです:
typedef struct {
int a, b, c;
} Type;
Type *t = malloc(sizeof *t);
*t = (Type) {
.a = 2,
.b = 3,
.c = 5,
};
の使用Type
、および*t
上記のコードからの削除はできますか?
あなたが尋ねたので;)コードの明示的な重複を避けるためにCには1つのツール、マクロがあります。とはいえ、少なくともタイプの名前を繰り返さない方法は見当たらない。しかし、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
for float型またはポインターの非標準表現を使用するアーキテクチャーでも、すべてのメンバーを正しく初期化します。注意: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
これは、への呼び出しが失敗したときにポインターの参照を解除することを回避するため、より優れています。一方、これは初期化子に順序を再導入するため、どちらも完全ではありません。
可変個引数マクロを使用できます。これが良い考えだとは言いませんが、うまくいきます。
#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
表示されない)ため、これを使用するコンテキストに注意する必要があることに注意してください。
個人的には、不必要な重複で幸せだと思います。
いいえ、それが指定された初期化子を使用する唯一の方法です。(Type){}がないと、コンパイラはコンテンツを検証する方法を知りません。