구조체 끝의 크기가 0인 배열
제가 수강하고 있는 시스템 프로그래밍 강좌의 교수님께서 오늘 끝에 길이가 0인 배열을 가진 구조를 정의하라고 말씀하셨습니다.
struct array{
size_t size;
int data[0];
};
typedef struct array array;
이 구조는 변수를 사용하여 배열을 정의하거나 초기화하는 데 유용합니다. 예를 들어 다음과 같습니다.
array *array_new(size_t size){
array* a = malloc(sizeof(array) + size * sizeof(int));
if(a){
a->size = size;
}
return a;
}
즉, 용을 사용합니다.malloc()
우리는 또한 크기 0의 배열에 메모리를 할당합니다.이것은 저에게 완전히 새로운 것이고, 제가 이해하기로는, 구조물은 반드시 연속적인 위치에 그들의 요소를 가지고 있지 않기 때문에 이상하게 보입니다.
에 있는 왜?array_new
를 모메할에 data[0]
입니까, 예를 들어 , 이하는것왜▁why▁say.
array * a = array_new(3);
a->data[1] = 12;
?
그가 우리에게 말한 것을 보면, 구조의 끝에 길이 0으로 정의된 배열은 구조의 마지막 요소 바로 뒤에 오는 것이 확실해 보이지만, 제가 이해하기로는, 다시 말하지만, 구조에 패딩이 있을 수 있기 때문에, 이것은 이상해 보입니다.
저는 또한 이것이 gcc의 특징일 뿐 어떤 표준으로도 정의되지 않는다는 것을 주변에서 보았습니다.이것이 사실입니까?
현재 C11 제6.7.2.1장에 언급된 것처럼 플렉시블 어레이 멤버라는 표준 기능이 있습니다.
기준을 인용하면,
이름이 지정된 멤버가 둘 이상인 구조의 마지막 요소는 불완전한 배열 유형을 가질 수 있습니다. 이를 유연한 배열 멤버라고 합니다.대부분의 경우 Flexible Array 멤버는 무시됩니다.특히, 구조의 크기는 생략된 것보다 후행 패딩이 더 많을 수 있다는 점을 제외하고는 유연한 배열 멤버가 생략된 것과 같습니다. [...]
구문은 다음과 같아야 합니다.
struct s { int n; double d[]; };
여기서 마지막 요소는 불완전한 유형(어레이 차원 없음, 0도 아님)입니다.
그래서, 당신의 코드는 다음과 같이 보여야 합니다.
struct array{
size_t size;
int data[ ];
};
표준에 부합해야 합니다.
예를 들어, 0 크기의 어레이를 예로 들자면, 이는 동일한 크기를 달성하기 위한 기존 방식("struct hack")이었습니다.전에C99
GCC는 유연한 어레이 멤버 기능을 에뮬레이트하기 위한 확장으로 이 기능을 지원했습니다.
당신의 교수님은 혼란스러워 합니다.그들은 제가 제로 사이즈 배열을 정의하면 무슨 일이 일어나는지 읽으러 가야 합니다.이것은 비표준 GCC 확장입니다. 유효한 C가 아니며 학생들에게 사용법(*)을 가르쳐야 하는 것이 아닙니다.
대신 표준 C Flexible Array 멤버를 사용합니다.제로 사이즈 어레이와 달리 실제로 작동합니다.
struct array{
size_t size;
int data[];
};
는 사용시 Flexible 레으멤 0로계다니산을 할 때 됩니다.sizeof
구조에서 다음과 같은 작업을 수행할 수 있습니다.
malloc(sizeof(array) + sizeof(int[size]));
(*) 90년대에 사람들은 "구조 해킹"으로 알려진 구조 뒤에 데이터를 추가하기 위해 안전하지 않은 공격을 사용했습니다.구조를 안전하게 확장할 수 있는 방법을 제공하기 위해 GCC는 비표준 확장으로 제로 크기 어레이 기능을 구현했습니다.1999년 C 표준이 마침내 더 나은 방법을 제공하면서 그것은 쓸모없게 되었습니다.
다른 답변에서는 길이가 0인 배열이 GCC 확장이고 C는 가변 길이 배열을 허용하지만 다른 질문은 아무도 다루지 않았다고 설명합니다.
제가 알기로는 구조물이 반드시 연속적인 위치에 있는 것은 아닙니다.
네.struct
데이터 유형에 연속된 위치에 반드시 요소가 있는 것은 아닙니다.
에 있는 왜?
array_new
를 모메할에data[0]
입니까, 예를 들어 , 이하는것왜▁why▁say.array * a = array_new(3); a->data[1] = 12;
?
길이가 0인 배열에 대한 제한 사항 중 하나는 구조의 마지막 멤버여야 한다는 것입니다.이를 통해 컴파일러는 구조체가 가변 길이 객체를 가질 수 있으며 런타임에 메모리가 더 필요하다는 것을 알고 있습니다.
그러나 "제로 길이 배열이 구조의 마지막 멤버이기 때문에 제로 길이 배열에 할당된 메모리는 구조의 끝에 추가되어야 하며 구조체가 연속적인 위치에 반드시 요소를 가지고 있지 않기 때문에 어떻게 할당된 메모리에 액세스할 수 있습니까?"와 혼동해서는 안 됩니다.
구조물 메모리 인 것은 그들 이 있을 수 , 할당된 는 variable로 합니다.data
그리고 네, 패딩은 여기에 영향을 미치지 않을 것입니다.15"입니다.
구조체 개체 내에서 비트 필드가 아닌 멤버와 비트 필드가 있는 장치에는 선언된 순서대로 증가하는 주소가 있습니다.
저는 또한 이것이 gcc의 특징일 뿐 어떤 표준으로도 정의되지 않는다는 것을 주변에서 보았습니다.이것이 사실입니까?
네. 이미 언급한 다른 답변처럼 제로 길이 어레이는 표준 C가 지원하지 않고 GCC 컴파일러의 확장입니다.C99는 플렉시블 어레이 멤버를 도입했습니다.C 표준(6.7.2.1)의 예:
선언 후:
struct s { int n; double d[]; };
구조물
s
유연한 어레이 멤버 포함d
일반적인 사용 방법은 다음과 같습니다.int m = /* some value */; struct s *p = malloc(sizeof (struct s) + sizeof (double [m]));
그리고 전화가 온 것을 가정하면.
malloc
success, 객체가 가리킴p
대부분의 목적을 위해 마치p
다음과 같이 선언되었습니다.struct { int n; double d[m]; } *p;
(이 등가성이 깨지는 상황이 있습니다; 특히, 구성원의 오프셋.
d
동일하지 않을 수 있음).
보다 표준적인 방법은 다음과 같이 데이터 크기가 1인 어레이를 정의하는 것입니다.
struct array{
size_t size;
int data[1]; // <--- will work across compilers
};
그런 다음 데이터 멤버의 오프셋(어레이 크기가 아님)을 계산에 사용합니다.
array *array_new(size_t size){
array* a = malloc(offsetof(array, data) + size * sizeof(int));
if(a){
a->size = size;
}
return a;
}
이는 크기에 따라 추가 데이터가 이동할 수 있는 위치에 대한 마커로 array.data를 효과적으로 사용하는 것입니다.
제가 예전에 했던 방법은 구조물의 끝에 더미 부재가 없는 것입니다. 구조물의 크기 자체가 구조물의 바로 뒤에 있는 주소를 알려줍니다.입력한 포인터에 1을 추가하면 다음과 같이 됩니다.
header * p = malloc (sizeof (header) + buffersize);
char * buffer = (char*)(p+1);
일반적으로 구조체의 경우 필드가 순서대로 배치되어 있음을 알 수 있습니다.파일 형식 이진 이미지, 운영 체제 호출 또는 하드웨어에 필요한 일부 부과된 구조를 일치시킬 수 있다는 것은 C를 사용하는 것의 장점 중 하나입니다.정렬을 위한 패딩이 어떻게 작동하는지 알아야 하지만, 그것들은 순서대로 하나의 연속된 블록 안에 있습니다.
언급URL : https://stackoverflow.com/questions/36577094/array-of-size-0-at-the-end-of-struct
'sourcecode' 카테고리의 다른 글
phpMyAdmin 오류: mysqli_real_connect(): (HY000/1045):'pma'@'localhost' 사용자에 대한 액세스가 거부되었습니다(암호 사용: 아니요). (0) | 2023.08.06 |
---|---|
혜성과 jQuery (0) | 2023.08.06 |
빠르게 원을 그리며 이미지를 설정하는 방법 (0) | 2023.08.06 |
Python 시간대 변환 (0) | 2023.08.06 |
충돌:여러 자산이 동일한 파일 이름으로 방출됨 (0) | 2023.08.01 |