programing

익명 구조/연합을 사용하여 C 코드를 컴파일하려면 어떻게 해야 합니까?

procenter 2022. 8. 28. 22:21
반응형

익명 구조/연합을 사용하여 C 코드를 컴파일하려면 어떻게 해야 합니까?

이것은 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

http://gcc.gnu.org/onlinedocs/gcc/Unnamed-Fields.html#Unnamed-Fields에 의하면

-fms-extensions필요한 기능을 유효하게 합니다.

또한 항상 다음을 수행할 수 있습니다.

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

편집증이 심해지고 싶다면 플랫폼에 맞는 데이터 패킹 전략을 수동으로 지정할 수 있습니다.

(이 답변은 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);

구조 내에 필드가 너무 많아지지 않도록 흥미로운 회피책을 제안할 수 있습니다.단순히 명명된 정의에 대해서는 충돌이 발생할 수 있으므로 경고하는 것이 좋습니다.

#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. */

새로운 C11 표준은 익명의 구조와 조합을 지원할 것이다. 2011년 4월 초안의 서문 단락 6을 참조한다.

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

이상한 점은 현재 gcc와 clang 모두 C89 및 C99 모드에서 익명 구조 및 유니언을 지원하고 있다는 점입니다.내 기계에는 경고가 표시되지 않는다.

익명 결합은 C++ 언어의 특징입니다.C 언어에는 익명 결합이 없습니다.

익명 구조는 C와 C++ 모두에 존재하지 않습니다.

질문에서 제시한 선언문은 GCC C++ 컴파일러로 컴파일 할 수 있지만 표준 C와 표준 C++ 어느 쪽과도 관련이 없는 컴파일러 고유의 확장일 뿐입니다.

게다가, 어떻게 실장하는지에 관계없이, C나 C++의 어느 언어도, 어설션이 유지되는 것을 보증하지 않습니다.

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:\>gcc vec.c - 벽

C:\>gcc --version gcc (GCC) 4.4.0 Copyright (C) 2009 Free Software Foundation, Inc.이것은 무료 소프트웨어입니다.복사 조건에 대해서는, 출처를 참조해 주세요.상품성이나 특정 목적에 대한 적합성에 대해서도 보증은 없습니다.

익명 조합은 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));

C의 GNU 방언은 어나니머스 구조/유니온을 지원하지만 기본적으로는 GCC는 일종의 표준 C를 사용하여 컴파일합니다.GNU 사투리를 사용하려면 명령줄에 "-std=sys99"를 입력합니다.

식별되지 않은 구조 멤버가 ANSI/ISO C99 표준이 아님을 설명하지만 재미있는 일이 발생합니다.GNU C 컴파일러 2.x.x 버전의 일부 포트에서는 미확정 구조 멤버를 사용하여 "x is not member of union", "x is what is x", "x is not member of union", "x"와 같은 것이 표시되지 않습니다.f structure, hell 난 맹세코 예전에 이것 때문에 "알 수 없는 포인터"를 본 적이 있어.

그래서 나는 전문적으로 다른 모든 사람과 함께 가서 단지 구조\union 멤버에게 식별자를 주거나 UNION의 경우 식별된 구조체의 식별된 멤버를 유니언으로 만들고 원래 유니언의 미확인 구조에 포함된 멤버를 ID의 멤버가 되도록 조심스럽게 코드를 재배치합니다.식별된 조합원과 함께 신중하게 사용되는 구조.그러나 그러한 경우, 후자의 방법은 실행 가능한 대체 방법이 아니기 때문에, 귀찮은 구조에 식별자를 붙이고 넘어갑니다.

언급URL : https://stackoverflow.com/questions/1972003/how-to-compile-c-code-with-anonymous-structs-unions

반응형