programing

유연한 배열 부재로 구조를 초기화하는 방법

magicmemo 2023. 9. 13. 22:31
반응형

유연한 배열 부재로 구조를 초기화하는 방법

나는 다음과 같은 구조를 가지고 있습니다.

typedef struct _person {
    int age;
    char sex;
    char name[];
}person;

를 사용하지 않고 인스턴스를 만들고 유연한 배열 멤버로 구조를 초기화하는 방법에 대해 몇 가지 기본적인 인터넷 검색을 했지만 실패했습니다.malloc().

예를 들어 다음과 같은 일반 구조의 경우

struct a {
    int age; 
    int sex;
};

우리는 예를 만들 수 있습니다.struct a이렇게 초기화를 합니다.

struct a p1 = {10, 'm'};

그러나 유연한 배열이 포함된 구조물의 경우(예:_person위에서 언급한 바와 같이) 인스턴스를 생성하고 일반적으로 수행하는 방법과 같이 초기화하는 방법structures?

그게 가능하긴 해요?그렇다면 초기화 시 어레이 크기와 초기화할 실제 값을 어떻게 전달합니까?

(또는)

유연한 배열로 구조를 만들 수 있는 유일한 방법은malloc()C99 사양에 언급된 바와 같이 -6.7.2.1 Structure and union specifiers - point #17?!

아니요, 유연한 배열은 항상 수동으로 할당해야 합니다.하지만 당신은 사용해도 좋습니다.calloc가요성 부품을 초기화하고 복합 리터럴을 사용하여 고정 부품을 초기화합니다.그것을 할당으로 포장하겠습니다.inline기능은 다음과 같습니다.

typedef struct person {
  unsigned age;
  char sex;
  size_t size;
  char name[];
} person;

inline
person* alloc_person(int a, char s, size_t n) {
  person * ret = calloc(sizeof(person) + n, 1);
  if (ret) memcpy(ret,
                  &(person const){ .age = a, .sex = s, .size = n},
                  sizeof(person));
  return ret;
}

발신자에게 할당이 성공했는지 확인합니다.

필요없다면,size여기에 포함시켰듯이 매크로로도 충분합니다.다만, 반품을 확인할 수는 없을 것입니다.calloc하기 전에memcpy. 제가 지금까지 프로그래밍한 모든 시스템에서 이것은 비교적 잘 중단될 것입니다.나는 일반적으로 의 반환은 중요하지 않다고 생각하지만, 그 주제에 대해서는 의견이 크게 다릅니다.

이것은 아마도 (그 특별한 경우) 최적화자에게 주변에 코드를 통합할 수 있는 더 많은 기회를 줄 수 있습니다.

#define ALLOC_PERSON(A,  S,  N)                                 \
((person*)memcpy(calloc(sizeof(person) + (N), 1),               \
                 &(person const){ .age = (A), .sex = (S) },     \
                 sizeof(person)))

편집: 기능보다 더 좋을 수 있는 경우는A그리고.S컴파일 시간 상수입니다.이 경우 복합 리터럴은const자격이 있고 정적으로 할당할 수 있으며 컴파일 시 초기화를 수행할 수 있습니다.또한 코드에 동일한 값의 할당이 여러 개 나타나면 컴파일러는 해당 복합 리터럴의 단일 복사본만 구현할 수 있습니다.

여러분이 사용할 수 있는 몇 가지 속임수가 있습니다.특정 용도에 따라 다릅니다.

단일 변수를 초기화하려면 올바른 크기의 구조를 정의할 수 있습니다.

   struct  {
        int age;
        char sex;
        char name[sizeof("THE_NAME")];
    } your_variable = { 55, 'M', "THE_NAME" };

문제는 포인터 캐스팅을 사용하여 변수를 "사람"(예: "*(사람 *)(&your_variable)"으로 해석해야 한다는 것입니다.그러나 이를 방지하기 위해 containing union을 사용할 수 있습니다.

union {
 struct { ..., char name[sizeof("THE_NAME")]; } x;
 person p;
} your_var = { 55, 'M', "THE_NAME" };

당신의_var.p는 "person" 타입입니다.매크로를 사용하여 이니셜라이저를 정의할 수도 있으므로 문자열을 한 번만 쓸 수 있습니다.

#define INIVAR(x_, age_, sex_ ,s_) \
   union {\
     struct { ..., char name[sizeof(s_)]; } x;\
     person p;\
    } x_ = { (age_), (sex_), (s_) }

INIVAR(your_var, 55, 'M', "THE NAME");

또 다른 문제는 이 트릭이 "사람"의 배열을 만들기에 적합하지 않다는 것입니다.배열의 문제점은 모든 요소의 크기가 같아야 한다는 것입니다.이 경우에는 a를 사용하는 것이 더 안전합니다.const char *에 대신에char[] ;)을 합니다. 또는 동적 할당을 사용합니다 ;)

플렉시블 어레이 부재를 갖는 구조 타입은 플렉시블 어레이 부재가 생략된 것처럼 취급할 수 있으므로, 이와 같이 구조를 초기화할 수 있습니다.

person p = { 10, 'x' };

그러나 할당된 Flexible Array의 멤버가 없으므로 Flexible Array의 멤버에 액세스하거나 해당 멤버를 넘어 다른 멤버로 포인터를 형성하려는 시도는 유효하지 않습니다. 있는 입니다. 를 들어이에가는열를진의를다는를은로한는로한e다는를로은한rrh이yrsefhsnaeeeoysnyy에hs는 예를 들어,malloc.

언급URL : https://stackoverflow.com/questions/8687671/how-to-initialize-a-structure-with-flexible-array-member

반응형