9

C99の指定された初期化子を、結果と組み合わせる良い方法はありmallocますか?

以下は不必要な重複があるようです:

typedef struct {
   int a, b, c;
} Type;

Type *t = malloc(sizeof *t);
*t = (Type) {
    .a = 2,
    .b = 3,
    .c = 5,
};

の使用Type、および*t上記のコードからの削除はできますか?

4

3 に答える 3

6

あなたが尋ねたので;)コードの明示的な重複を避けるために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,
);

これにはいくつかの利点があります。

  • 0for float型またはポインターの非標準表現を使用するアーキテクチャーでも、すべてのメンバーを正しく初期化します。
  • キースのバージョンを除いて、それは初期化のように見える単なる式であり、誰もが2番目のコードスニペットが行うことになっていることをすぐに視覚的にキャプチャする必要があるため、「コーディングスタイル」として受け入れられます。

注意: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これは、への呼び出しが失敗したときにポインターの参照を解除することを回避するため、より優れています。一方、これは初期化子に順序を再導入するため、どちらも完全ではありません。

于 2011-09-22T06:31:20.153 に答える
2

可変個引数マクロを使用できます。これが良い考えだとは言いませんが、うまくいきます。

#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表示されない)ため、これを使用するコンテキストに注意する必要があることに注意してください。

個人的には、不必要な重複で幸せだと思います。

于 2011-09-01T03:18:59.997 に答える
1

いいえ、それが指定された初期化子を使用する唯一の方法です。(Type){}がないと、コンパイラはコンテンツを検証する方法を知りません。

于 2011-09-01T02:46:25.833 に答える