将结构传递给函数并将值存储在结构的元素中

时间:2017-10-11 07:51:51

标签: c arrays pointers memory-management malloc

我想将结构传递给函数并将值存储在结构的元素中。这是我的代码。

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

typedef struct {
    uint32_t len;
    uint16_t *arr;
} seq;

void write_seq(seq *q, int val)
{
    // How to implement this function?

    uint16_t *tmp;
    tmp = (uint16_t *)malloc(sizeof(uint16_t));
    *tmp = val;

    *(q->arr + q->len) = *tmp;
    q->len += 1;

}

int main(int argc, char *argv[])
{
    seq q;
    q.len = 0;
    q.arr = NULL;
    int i;
    for (i = 0; i < 10; i++) {
        write_seq(&q, i);
    }

    printf("length is %d\n", q.len);
    for (i = 0; i < q.len; i++) {
        printf("%d\n", *(q.arr+i));

    }

    return 0;
}

我想将0到9写入q.arr指向的内存块 我不想在main()中使用malloc,因为在调用write_seq之前我不知道需要多少字节。我想在每次调用write_seq时找到新的内存。这是输出的样子。

length is 10
0
1
2
3
4
5
6
7
8
9

我的write_seq()实现会导致核心转储。我不知道如何解决它。谢谢。

2 个答案:

答案 0 :(得分:1)

您需要使用realloc(),而不是malloc(),如下所示:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

typedef struct {
    int len;
    int *arr;
} seq;

void write_seq(seq *q)
{
    q->arr = realloc (q->arr, (q->len + 1) *  sizeof(int));
    q->arr[q->len] = q->len;
    q->len++;
}

int main(void)
{
    seq q;
    q.len = 0;
    q.arr = NULL;

    for(int i = 0; i < 10; ++i)
        write_seq(&q);


    printf("length is %d\n", q.len);
    for (int i = 0; i < q.len; i++) {
        printf("%d\n", q.arr[i]);
    }

    free(q.arr);

    return 0;
}

输出:

length is 10
0
1
2
3
4
5
6
7
8
9

答案 1 :(得分:1)

如果您事先不知道该阵列的大小,要向阵列添加成员,则需要使用realloc()按需增加大小。但是,对于每次更改数组大小来执行此操作效率很低,因此更常见的是允许一定量的净空(无论是固定增量还是基于百分比的数量)缓冲液中。

其必然结果是您需要将缓冲区的当前容量以及偏移量存储到当前使用的数量。

这也意味着会有一定量的内存浪费,但这是你必须做出的权衡。

我的方法看起来像这样,抽象出你可能希望在seq上执行的操作。

typedef struct {
    size_t    capacity;
    size_t    offset;
    uint16_t *arr;
} seq;

static const size_t SEQ_INITIAL = 8;
static const size_t SEQ_INCREMENT = 8;

int seq_init(seq *seq) {
    assert(seq != NULL);         /* catch null seq */
    assert(seq->arr == NULL);    /* error to call on already init'd seq */
    seq->capacity = SEQ_INITIAL;
    seq->offset = 0;
    seq->arr = malloc(seq->capacity * sizeof(seq->arr[0]));
    return seq->arr == NULL ? -1 : 0;
}

static int seq_grow(seq *seq) {  /* private implementation detail */
    size_t new_capacity = seq->capacity + SEQ_INCREMENT;
    void *p = realloc(seq->arr, new_capacity * sizeof(seq->arr[0]));
    if (p == NULL) {             /* realloc failed, seq unmodified */
        return -1;
    }
    seq->arr = p;
    seq->capacity = new_capacity;
    return 0;
}

int seq_write(seq *seq, uint16_t value) {
    assert(seq != NULL);         /* catch null seq */ 
    if ((seq->offset == seq->capacity) && seq_grow(seq) < 0) {
        return -1;               /* write failed */
    }
    assert(seq->arr != NULL);    /* catch bad seq */
    assert(seq->offset < seq->capacity); /* ensure seq really has room */
    seq->arr[seq->offset++] = value;
    return 0;
}

void seq_free(seq *seq) {
    if (seq != NULL) {
        free(seq->arr);
        seq->arr = NULL;
    }
}