C에서 malloc 및 realloc을 사용하여 구조체 내에서 배열을 올바르게 할당하는 방법은 무엇입니까?

딜런

저는 C로 스택을 구현하는 동시에 C를 배우려고 노력하고 있습니다. 제 배경은 대부분 고등 언어 (예 : Python)에 있으므로 많은 메모리 할당이 저에게 새로운 것입니다.

예상대로 작동하는 프로그램이 있지만 내가 뭔가 잘못하고 있다고 믿게 만드는 경고를 표시합니다.

다음은 코드입니다.

typedef struct {
    int num_items;
    int top;
    int items[];
} stack;

void push(stack *st, int n) {
    st->num_items++;

    int* tmp = realloc(st->items, (st->num_items) * sizeof(int));

    if (tmp) {
        *(st->items) = tmp;
    }

    st->items[st->num_items - 1] = n;
    st->top = n;
}

int main() {
    stack *x = malloc(sizeof(x));
    x->num_items = 0;
    x->top = 0;
    *(x->items) = malloc(0);

    push(x, 2);
    push(x, 3);

    printf("Stack top: %d, length: %d.\n", x->top, x->num_items);

    for (int i = 0; i < x->num_items; i++) {
        free(&(x->items[i]));
    }
    free(x->items);
    free(x);
}

출력은 다음과 같습니다.

Stack top: 3, length: 2.

어느 것이 예상됩니다. 그러나 컴파일 중에 다음과 같은 오류가 발생합니다.

> gcc -x c -o driver driver.c
driver.c: In function 'push':
driver.c:16:16: warning: assignment makes integer from pointer without a cast
    *(st->items) = tmp;
...
driver.c: In function 'main':
driver.c:27:14: warning: assignment makes integer from pointer without a cast
    *(x->items) = malloc(0);
Antti Haapala

당신의 믿음이 맞습니다. 일반적으로 거의 항상 그렇습니다. C 컴파일러의 경고는 심각한 문제를 일으킬 수있는 심각한 프로그래밍 오류의 신호입니다. 다양한 프로그래밍 언어로 발에 자신을 쏘아 올리기 :

  • 당신은 발에 총을 쏜다.
  • 당신은 발에 총을 쏘면 아무도 당신이 한 일을 알아낼 수 없습니다.

문제는 int items에 대한 포인터 처럼 코딩하고 있지만 완전히 다른 짐승 인 FAM ( Flexible Array Member) 으로 선언하고 정의 했다는 것 입니다. 그리고 이후 배열에 할당하는 오류가 발생 것 , 즉

x->items = malloc(0);

오류가 될 수 있으며 경고만으로 컴파일되는 무언가를 생각해 냈습니다. 오류는 경고보다 낫다는 것을 기억하십시오.


해결책은 대신에 items대한 포인터로int 선언 하는 것입니다.

int *items;

그리고 사용

x->items = ...;

기대하는 포인터 동작을 얻으려면.

또한,

free(&(x->items[i]));

i첫 번째 정수를 할당하지 않았기 때문에 매우 잘못 되었습니다. 그들은 배열의 객체였습니다. 또한 필요하지 않습니다 malloc(0). null 포인터로 초기화하십시오.

x->items = NULL;

realloc그리고 free널 포인터는 신경 쓰지 않을 것입니다.


유연한 배열 구성원은 구조의 마지막 요소가 무한 길이의 배열이므로 malloc충분한 메모리를 예약 할 수 있음을 의미합니다.

stack *x = malloc(sizeof x + sizeof *x->items * n_items);

가요 어레이 구성원과 같은 개체의 CPython에서 사용되는 str, bytes또는 tuple불변 길이 있는지 -이 다른 포인터 대신 FAM을 사용하여 약간 빠르며, 그것은 메모리에 저장 - 특히 짧은 문자열 또는 튜플.


마지막으로, 스택이 커질수록 느려집니다. 그 이유는 항상 하나의 요소 만 더 할당하기 때문입니다. 대신 삽입이 시간 내에 실행되도록 인수 (1.3, 1.5, 2.0?)로 스택의 크기를 조정해야 O(1)합니다 O(n). 그리고 어떤 일이 일어날 지 생각해보십시오. realloc아마도 당신은 그것에 대해 더 크게해야합니다!

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

Related 관련 기사

뜨겁다태그

보관