벡터의 길이와 그 값을 나타내는 구조를 다음과 같이 정의한다고 가정합니다.
struct Vector{
double* x;
int n;
};
이제 벡터 y를 정의하고 여기에 메모리를 할당한다고 가정합니다.
struct Vector *y = (struct Vector*)malloc(sizeof(struct Vector));
인터넷을 통한 검색 결과 x에 대한 메모리를 별도로 할당해야한다는 것을 알 수 있습니다.
y->x = (double*)malloc(10*sizeof(double));
하지만 y-> x에 메모리를 두 번 할당하는 것 같습니다. 하나는 y에 메모리를 할당하고 다른 하나는 y-> x에 메모리를 할당하면서 메모리 낭비로 보입니다. 컴파일러가 실제로하는 일과 y와 y-> x를 모두 초기화하는 올바른 방법이 무엇인지 알려 주시면 대단히 감사하겠습니다.
미리 감사드립니다.
답변
아니요, 메모리를 두 번 할당 하지 않습니다y->x
.
대신 (포인터 포함) 구조에 대한 메모리를 할당하고 플러스 를 차례로 그 포인터를 위해 무언가를.
다음과 같이 생각하십시오.
1 2
+-----+ +------+
y------>| x------>| *x |
| n | +------+
+-----+
따라서 실제로 모든 것을 저장 하려면 두 개의 할당 ( 1
및 2
)이 필요합니다 .
추가적으로, 당신의 타입은 struct Vector *y
포인터이기 때문에 절대로 malloc
C 에서 반환 값을 캐스트해서는 안됩니다. 숨기고 싶지 않은 특정 문제를 숨길 수 있기 때문입니다. C는 void*
반환 값을 다른 포인터로 암시 적으로 변환 할 수 있습니다.
물론 다음과 같이 벡터를보다 쉽게 관리 할 수 있도록 이러한 벡터 생성을 캡슐화하고 싶을 것입니다.
struct Vector {
double *data; // no place for x and n in readable code :-)
size_t size;
};
struct Vector *newVector (size_t sz) {
// Try to allocate vector structure.
struct Vector *retVal = malloc (sizeof (struct Vector));
if (retVal == NULL)
return NULL;
// Try to allocate vector data, free structure if fail.
retVal->data = malloc (sz * sizeof (double));
if (retVal->data == NULL) {
free (retVal);
return NULL;
}
// Set size and return.
retVal->size = sz;
return retVal;
}
void delVector (struct Vector *vector) {
// Can safely assume vector is NULL or fully built.
if (vector != NULL) {
free (vector->data);
free (vector);
}
}
이와 같이 창조물을 캡슐화함으로써 벡터가 완전히 빌드되었는지 또는 전혀 빌드되지 않았는지 확인합니다. 벡터가 절반으로 빌드 될 가능성이 없습니다. 또한 클라이언트에 영향을주지 않고 향후 기본 데이터 구조를 완전히 변경할 수 있습니다 (예를 들어, 속도를 위해 공간을 절충하기 위해 희소 배열로 만들려는 경우).
답변
처음에는에 대한 메모리를 할당합니다 Vector
. 이는 변수 x
, 를 의미합니다 n
.
그러나 x
아직 유용한 것은 없습니다 .
그래서 두 번째 할당도 필요합니다 .
답변
몇 가지 포인트
struct Vector y = (struct Vector*)malloc(sizeof(struct Vector));
틀렸다
에 대한 포인터를 보유하고 있기 struct Vector *y = (struct Vector*)malloc(sizeof(struct Vector));
때문에 .y
struct Vector
1st malloc()
는 Vector 구조 (double + int에 대한 포인터)를 보유하기에 충분한 메모리 만 할당합니다.
두 번째는 malloc()
실제로 메모리를 할당하여 10을 두 배로 유지합니다.
답변
실제로 벡터와 배열을 동시에 할당하여 단일 malloc에서이를 수행 할 수 있습니다. 예 :
struct Vector y = (struct Vector*)malloc(sizeof(struct Vector) + 10*sizeof(double));
y->x = (double*)((char*)y + sizeof(struct Vector));
y->n = 10;
이것은 Vector ‘y’를 할당 한 다음, y-> x가 Vector 구조체 바로 뒤에 할당 된 추가 데이터를 가리 키도록합니다 (그러나 동일한 메모리 블록에 있음).
벡터의 크기를 조정해야하는 경우 권장되는 두 가지 할당으로 수행해야합니다. 내부 y-> x 배열은 벡터 구조체 ‘y’를 그대로 유지하면서 크기를 조정할 수 있습니다.
답변
원칙적으로 이미 올바르게하고 있습니다. 당신이 원하는 것을 위해 두 개의 malloc()
s 가 필요합니다 .
몇 가지 의견 :
struct Vector y = (struct Vector*)malloc(sizeof(struct Vector));
y->x = (double*)malloc(10*sizeof(double));
해야한다
struct Vector *y = malloc(sizeof *y); /* Note the pointer */
y->x = calloc(10, sizeof *y->x);
첫 번째 줄에서는 Vector 객체에 대한 메모리를 할당합니다. malloc()
할당 된 메모리에 대한 포인터를 반환하므로 y는 벡터 포인터 여야합니다. 두 번째 줄에서는 10 개의 double 배열에 메모리를 할당합니다.
C에서는 명시 적 캐스트가 필요하지 않으며, sizeof *y
대신 쓰는 것이 sizeof(struct Vector)
유형 안전성에 더 좋으며 입력 비용을 절약합니다.
구조체를 재정렬하고 다음과 malloc()
같이 단일 작업을 수행 할 수 있습니다 .
struct Vector{
int n;
double x[];
};
struct Vector *y = malloc(sizeof *y + 10 * sizeof(double));
답변
메모리를 할당 할 때 struct Vector
포인터 x
, 즉 주소를 포함하는 값이 배치되는 공간에 대한 메모리를 할당하면 됩니다. 따라서 y.x
참조 할 블록에 메모리를 할당하지 않습니다 .
답변
첫 번째 malloc은 x (double에 대한 포인터)에 대한 메모리를 포함하여 struct에 대한 메모리를 할당합니다. 두 번째 malloc은 x가 가리키는 double 값에 대한 메모리를 할당합니다.