3

このコードではsizeof(x)、タイプのサイズではなく、ポインターのサイズがなぜxですか?

typedef struct {
  ...
} x;

void foo() {
  x *x = malloc(sizeof(x));
}
4

3 に答える 3

6

Cが言うので:

(C99、6.2.1p7)「他の識別子には、宣言子の完了直後に開始するスコープがあります。」

したがって、あなたの例では、オブジェクトのスコープは:xの直後から始まります。x *x

x *x = /* scope of object x starts here */
       malloc(sizeof(x));

納得させるには、オブジェクトxの宣言の直後に別のタイプのオブジェクト宣言を配置しますx。コンパイルエラーが発生します。

void foo(void)
{
    x *x = malloc(sizeof(x));  // OK
    x *a;   // Error, x is now the name of an object
}

そうでなければ、Shahbazが別の回答のコメントで注目しているように、これはまだ正しい使用法ではありませんmalloc。あなたはmallocこのように呼ぶべきです:

T *a = malloc(sizeof *a);

ではなく

T *a = malloc(sizeof a);
于 2012-06-10T11:48:19.807 に答える
5

これは、ポインタであるsizeof(x)の最も内側の定義を使用しているためです。xこの問題を回避するには、型と変数に同じ名前を使用しないでください。

于 2012-06-10T11:34:32.547 に答える
0

(プログラミングだけでなく)異なるものに異なる名前を付けないことは悪い考えです:

行動オブザーバーの学術的理由は、私の親愛なる仲間のアノテーターによってすでに言及されていました。

明確なアドバイスを与えるために、名前の違いは異なります(ここでは:変数タイプと変数インスタンス):

typedef struct {
  ...
} X;

void foo() {
  X *x = malloc(sizeof(X));
}

この例をコーディングするさらに柔軟な方法は次のとおりです(Shahbazのコメントでもすでに述べられています)。

typedef struct {
  ...
} X;

void foo() {
  X *x = malloc(sizeof(*x));
}

後者の例ではx、割り当てを行うコードを変更せずに、のタイプを変更できます。

このアプローチの欠点はx、コンパイラーからの通知なしに、配列およびverse vica(の型として)への参照の使用から切り替えて、コードを壊す可能性があることです。

于 2012-06-10T11:57:55.177 に答える