유연한 배열 부재로 구조를 초기화하는 방법
나는 다음과 같은 구조를 가지고 있습니다.
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
'programing' 카테고리의 다른 글
리스트 스타일 이미지 위치를 조정하시겠습니까? (0) | 2023.09.13 |
---|---|
IE9에서 이진 데이터를 읽는 방법? (0) | 2023.09.13 |
펫클리닉보다 더 큰 오픈소스 스프링 샘플 프로젝트가 있습니까? (0) | 2023.09.13 |
Android 응용 프로그램에서 텍스트 뷰의 첫 글자를 대문자로 쓰는 방법 (0) | 2023.09.13 |
ORDER BY 절을 사용하거나 사용하지 않는 파티션에 대한 분석 카운트 (0) | 2023.09.13 |