c - 함수 - 유연한 배열 구성원이 정말로 필요합니까?




동적 배열 함수 (2)

그 개념들은 당신이 지적한대로 반드시 필요한 것은 아닙니다.

두 가지의 차이점은 데이터가 메모리에 저장되는 위치입니다.

유연한 배열을 사용하는 첫 번째 예제에서 메타 데이터와 배열 자체는 동일한 메모리 블록에 있으며, 필요한 경우 하나의 블록 (포인터)으로 이동할 수 있습니다.

두 번째 예제에서 메타 데이터는 스택에 있고 배열은 힙에 있습니다. 이동 / 복사하려면 두 블록의 메모리를 이동하고 메타 데이터 구조에서 포인터를 업데이트해야합니다.

일반적으로 가변 크기 배열은 배열을 배치해야 할 때 사용되며 메타 데이터는 공간적으로 함께 메모리에 저장됩니다.

이것이 확실히 유용한 예제는 메타 데이터가있는 배열을 파일에 배치하는 경우입니다. 하나의 연속적인 메모리 블록 만 있고로드 할 때마다 (대부분) VM의 다른 위치에 배치됩니다 .

명백히 유연한 배열 멤버가있는 구조체는 선언되지 않고 해당 구조체에 대한 포인터와 함께 사용됩니다. 유연한 배열 멤버를 선언 할 때 적어도 하나 이상의 다른 멤버가 있어야하며 유연한 배열 멤버는 해당 구조체의 마지막 멤버 여야합니다.

다음과 같은 모양이 있다고 가정 해 봅시다.

struct example{
    int n;
    int flm[]; 
}

그런 다음이를 사용하기 위해 포인터를 선언하고 malloc을 사용하여 구조체 내용의 메모리를 예약해야합니다.

struct example *ptr = malloc(sizeof(struct example) + 5*sizeof(int)); 

즉, flm [] 배열에 5 개의 정수가 저장되기를 원한다면 말입니다. 그럼, 난 그냥이 같은 내 구조체를 사용할 수 있습니다 :

ptr->flm[0] = 1; 

내 질문은, 대신이 대신 포인터를 사용할 수 있을까요? 뿐만 아니라 pre-C99와 호환 될 수있을뿐만 아니라 구조체에 대한 포인터를 사용하거나 사용하지 않고 사용할 수 있습니다. malloc을 flm과 함께 사용해야한다는 것을 고려할 때,이 작업을 수행 할 수 없습니까?

예제 구조체의 새로운 정의를 생각해보십시오.

struct example{
    int n; 
    int *notflm; 
}

struct example test = {4, malloc(sizeof(int) * 5)}; 

나는 심지어 유연한 배열 멤버와 같은 방식으로 교체를 사용할 수있을 것이다.

이것도 작동할까요? (위의 notflm 예제의 정의를 제공)

struct example test; 
test.n = 4; 
notflm = malloc(sizeof(int) * 5); 

포인터는 배열이 아닙니다. 사용할 배열을 선택하는 기본적인 이유는 배열 대 포인터의 경우와 동일합니다. 유연한 배열 멤버의 특별한 경우 다음은 포인터를 통해 선호하는 몇 가지 이유입니다.

  • 스토리지 요구 사항 감소. 포인터는 구조체를 (일반적으로) 4 또는 8 바이트 씩 확장 할 것이고, malloc 을 한 번 호출하는 것보다는 pointed-to-storage를 개별적으로 할당하는 경우 훨씬 많은 오버 헤드를 사용할 수 있습니다.

  • 액세스 효율성 향상. 플렉시블 어레이 부재는 구조베이스로부터 일정한 오프셋에 위치합니다. 포인터는 별도의 역 참조가 필요합니다. 이는 액세스에 필요한 명령 수와 레지스터 압박에 모두 영향을줍니다.

  • 할당 성공 / 실패의 원 자성. 구조를 할당하고 두 개의 별도 단계로 가리 키도록 저장소를 할당하는 경우 실패 사례에서 정리를위한 코드는 성공한 사례와 실패한 사례가 있기 때문에 훨씬 못 생깁니다. 같은 malloc 요청을 처리하기 위해 포인터 연산을 사용하지 않아도되지만, 정렬 문제로 인해 논리를 잘못 처리하고 UB를 호출하기 쉽습니다.

  • 깊은 사본의 필요성을 피하십시오. 포인터 대신 유연한 배열을 사용하는 경우 지적 된 데이터를 복사하지 않고 구조체를 복사하고 포인터를 수정하지 않고 단순히 memcpy (할당이 유연한 배열 길이를 알 수 없으므로 할당하지 않음)를 사용하면됩니다. 새 사본에.

  • 깊은 자유에 대한 필요성을 피하십시오. pointed-to 데이터를 free 하는 것보다 단일 객체를 free 하는 것이 매우 편리하고 깨끗합니다. 물론 위에서 언급 한 "단일 malloc 조각"을 사용하여이 작업을 수행 할 수도 있지만 유연한 배열을 사용하면 오류가 발생하기 쉽고 간단합니다.

  • 확실히 더 많은 이유가 ...





flexible-array-member