69

私はこれをc++/ g++で行うことができます:

struct vec3 { 
    union {
        struct {
            float x, y, z;
        }; 
        float xyz[3];
    }; 
};

それで、

vec3 v;
assert(&v.xyz[0] == &v.x);
assert(&v.xyz[1] == &v.y);
assert(&v.xyz[2] == &v.z);

動作します。

gccを使用してcでこれをどのように行うのですか?私は持っています

typedef struct {
    union {
        struct {
            float x, y, z;
        };
        float xyz[3];
    };
} Vector3;

しかし、特にエラーが発生します

line 5: warning: declaration does not declare anything
line 7: warning: declaration does not declare anything
4

10 に答える 10

54

http://gcc.gnu.org/onlinedocs/gcc/Unnamed-Fields.html#Unnamed-Fieldsによると

-fms-extensionsあなた(そして私)が望む機能を有効にします。

于 2010-03-06T02:08:19.510 に答える
33

(この回答はC11ではなくC99に適用されます)。

C99には匿名の構造や結合はありません。それらに名前を付ける必要があります:

typedef struct {
    union {
        struct {
            float x, y, z;
        } individual;
        float xyz[3];
    } data;
} Vector3;

そして、それらにアクセスするときに名前を使用する必要があります。

assert(&v.data.xyz[0] == &v.data.individual.x);

この場合、最上位の構造には共用体型の単一の項目があるため、これを単純化できます。

typedef union {
    struct {
        float x, y, z;
    } individual;
    float xyz[3];
} Vector3;

データへのアクセスは次のようになります。

assert(&v.xyz[0] == &v.individual.x);
于 2009-12-28T23:18:02.877 に答える
25

新しいC11標準は、匿名の構造体と共用体をサポートします。2011年4月のドラフトの序文の段落6を参照してください。

http://en.wikipedia.org/wiki/C1X

奇妙な部分は、gccとclangの両方がC89およびC99モードで匿名構造体と共用体をサポートするようになったことです。私のマシンでは警告は表示されません。

于 2011-11-11T20:39:40.413 に答える
12

また、常に次のことを行うことができます。

typedef struct
{
    float xyz[0];
    float x, y, z;
}Vec3;

長さがゼロの配列はストレージを割り当てず、Cに「次に宣言されるものを指す」ように指示するだけです。次に、他のアレイと同じようにアクセスできます。

int main(int argc, char** argv)
{
    Vec3 tVec;
    for(int i = 0; i < 3; ++i)
    {
        tVec.xyz[i] = (float)i;
    }

    printf("vec.x == %f\n", tVec.x);
    printf("vec.y == %f\n", tVec.y);
    printf("vec.z == %f\n", tVec.z);

    return 0;
}

結果:

vec.x == 0.000000
vec.y == 1.000000
vec.z == 2.000000

余分なパラノイアになりたい場合は、プラットフォームに合わせてデータパッキング戦略を手動で指定できます。

于 2013-07-10T21:17:23.843 に答える
8

匿名ユニオンはC++言語の機能です。C言語には匿名の結合はありません。

匿名の構造体は、CにもC++にも存在しません。

質問で提示した宣言はGCCC++コンパイラでコンパイルされる可能性がありますが、これはコンパイラ固有の拡張であり、標準Cにも標準C++にも関係ありません。

その上、実装方法に関係なく、C言語もC ++言語も、アサーションが保持されることを保証しません。

于 2009-12-28T23:14:21.030 に答える
3

警告なしにGCCでこれを行うことができます

typedef union {
    struct { // human-friendly access
        float x;
        float y;
        float z;
        float w;
    };
    float xyz[3];
    struct { // human-friendly access
        float r;
        float g;
        float b;
        float a;
    };
    float rgb[3];
} Vector4f;

int main()
{
    Vector4f position, normal, color;
    // human-friendly access
    position.x = 12.3f;
    position.y = 2.f;
    position.z = 3.f;
    position.w = 1.f;

    normal.x = .8f;
    normal.y = .9f;
    normal.z = .1f;
    normal.w = 1.f;

    color.r = 1.f;
    color.g = .233f;
    color.b = 2.11f;
    color.a = 1.1f;

    // computer friendly access
    //some_processor_specific_operation(position.vec,normal.vec);
    return 0;
}

C:\>gccvec.c-壁

C:\> gcc --version gcc(GCC)4.4.0 Copyright(C)2009 Free Software Foundation、Inc.これはフリーソフトウェアです。コピー条件については、ソースを参照してください。保証はありません。商品性や特定の目的への適合性についてもそうではありません。

于 2010-01-29T19:05:11.233 に答える
2

匿名ユニオンはCではサポートされていません。

また、このように宣言する場合は、次の点にも注意してください。

typedef struct {
    union {
        struct {
            float x, y, z;
        } individual;
        float xyz[3];
    } data;
} Vector3;

やってる

Vector3 v;
v.data.xyz[0] = 5;

float foo = v.data.individual.x;

未定義の動作です。最後に割り当てられた組合員にのみアクセスできます。あなたの場合、ユニオンを使用することは、標準で指定されていない多くのことに依存しているため、間違っており、悪いコーディング慣行です(パディング...)。

Cでは、次のようなものを好みます。

typedef struct {
    float v[3];
} Vec3;

また、v [x]を使用したくない場合は、次のことを検討してください。

#define X(V) ((V).v[0])

Vec3 v;
X(v) = 5.3;
printf("%f\n", X(v));
于 2009-12-28T23:26:47.940 に答える
0

CのGNUダイアレクトは、匿名の構造体/ユニオンをサポートしますが、デフォルトでは、GCCはある種の標準Cを使用してコンパイルします。GNUダイアレクトを使用するには、コマンドラインに「-std=gnu99」を入力します。

于 2010-07-19T18:01:54.673 に答える
0

ANSI / ISO C99標準ではない未確認の構造体メンバーがこれを説明していますが、GNU Cコンパイラ2.xxバージョンの一部のポートでは、未確認の構造体メンバーを使用すると、機能することがわかり、「 xはunion\struct yのメンバーではありません、xとは何ですか? 「これが原因で、たまに前に。

だから私は、専門的にこれについて他のみんなと一緒に行き、struct \ unionメンバーに識別子を与えるか、UNIONの場合は、コードを慎重に再配置して、unionが識別された構造の識別されたメンバーと元のユニオンの未確認の構造体に埋め込まれ、特定された構造体のメンバーになり、特定されたユニオンメンバーと慎重に使用されます。しかし、これらの場合、後者の方法が実行可能な代替手段ではない場合、私は迷惑な構造に識別子を与えて先に進みます。

于 2010-07-27T10:58:32.873 に答える
-1

構造内のフィールドが多すぎないようにするために、興味深い回避策を提案できます。競合が発生する可能性があるため、単純に名前が付けられた定義について警告することをお勧めします。

#define x    ___fl_fld[0]
#define y    ___fl_fld[1]
#define z    ___fl_fld[2]
#define w    ___fl_fld[3]
#define r    ___fl_fld[0]
#define g    ___fl_fld[1]
#define b    ___fl_fld[2]
#define a    ___fl_fld[3]
typedef union {
    float ___fl_fld[4];
    float xyz[3];
    float rgb[3];
} Vector3;

次のような構造にアクセスできます。

Vector3 v;
assert(&v.x == &v.r); //Should return true

最後に、これはC99と互換性のあるマルチタイプの共用体になります。

#define u8llsb __u8[0]
#define u8lmsb __u8[1]
#define u8mlsb __u8[2]
#define u8mmsb __u8[3]
#define u16lsb __u16[0]
#define u16msb __u16[1]
#define u16    __u16[0]
#define u8lsb  __u8[0]
#define u8msb  __u8[1]

typedef union {
    uint32_t u32;
    int32_t  i32;
    uint16_t  __u16[2];
    uint8_t   __u8[4];
} multitype_t;

multitype_t Var;
var.u32;
var.i32;
var.u8llsb;
/* etc. */
于 2012-05-24T14:33:34.813 に答える