【问题标题】:Is there a way to execute the additem function without modifying values of two pointers?有没有办法在不修改两个指针的值的情况下执行 additem 函数?
【发布时间】:2015-10-11 04:04:12
【问题描述】:

这是我的代码:

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

typedef struct{
    unsigned long sz;
    char *item;
} itemset;

void additem(char** ram,itemset** items,char* thing){
    unsigned long sz=strlen(thing);
    if (sz > 20000 || sz < 1){return;}
    (**items).item=*ram;
    (*ram)+=sz;
    (**items).sz=sz;
    memcpy((char*)((**items).item),thing,sz);
    (*items)++;
}

void showitems(itemset* items){
    unsigned long ct=1;
    while(items->sz > 0){
        char buf[items->sz+2];
        memset(buf,0,items->sz+2);
        memcpy(buf,items->item,items->sz);
        printf("Item %d: size: %d = %s\n",ct,items->sz,buf);
        items++;ct++;
    }
}

int main(){
    char itembuf[50000];
    itemset* myitems=(itemset*)itembuf;
    char* mp=calloc(1,100000);
    char* wmp=mp;
    itemset* items=myitems;
    additem(&wmp,&myitems,"Test");
    additem(&wmp,&myitems,"Tests");
    additem(&wmp,&myitems,"Tester");
    additem(&wmp,&myitems,"Testing");
    showitems(items);
    printf("%s\n",mp);
    free(mp);

}

执行后,屏幕上会显示正确的输出,如下所示:

Item 1: size: 4 = Test
Item 2: size: 5 = Tests
Item 3: size: 6 = Tester
Item 4: size: 7 = Testing
TestTestsTesterTesting

要使 additem 函数工作,它需要两个自动更新的指针。一个更新文本的ram内存地址,一个更新结构的堆栈内存地址。

我想知道是否有一种方法可以更新函数并调用它,以便只传递和更新一个指针。例如:

additem(&stuff,"Test");

我希望整个程序功能保持不变,但我不想在结构内使用固定字符数组,因为这会浪费宝贵的内存。

【问题讨论】:

  • 这个问题可能更适合 Code Review codereview.stackexchange.com
  • 您总是可以将多个值捆绑在一个结构中并传递指向它的指针。然后,您可以编写函数来初始化该结构并清理它。调用代码永远不必担心保持所有变量同步。

标签: c function pointers memory-management


【解决方案1】:

将属于您的 item-set-cum-char-buffer 的所有内容捆绑在 struct 中,然后将指向该结构的指针传递给您的函数。当你不修改结构时,例如当你打印项目集时,传递一个const 指针。

您还应该提供初始化和清理项目集的函数,以便客户端代码不必担心集合的实现细节。

您的代码可能如下所示:

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

typedef struct{
    size_t length;
    char *str;
} Item;

typedef struct {
    size_t bufsize;         /* fixed size of the char buffer */
    size_t buflen;          /* currently used size of buffer */
    char *buf;
    size_t maxitem;         /* max. number of items */
    size_t count;           /* current number of items */
    Item *item;
} Itemset;

int iset_init(Itemset *iset, size_t maxitem, size_t bufsize)
{
    iset->buflen = 0;
    iset->bufsize = bufsize;
    iset->buf = malloc(bufsize);

    iset->count = 0;
    iset->maxitem = maxitem;
    iset->item = malloc(maxitem * sizeof(*iset->item));

    if (iset->item && iset->buf) return 0;

    free(iset->item);
    free(iset->buf);
    return -1;
}

int iset_add(Itemset *iset, char* str)
{
    size_t sz = strlen(str);

    if (iset->count >= iset->maxitem) return -1;
    if (iset->buflen + sz + 1 > iset->bufsize) return -1;

    iset->item[iset->count].str = &iset->buf[iset->buflen];
    iset->item[iset->count].length = sz;
    iset->count++;

    strcpy(&iset->buf[iset->buflen], str);
    iset->buflen += sz + 1;

    printf("%zu\n", iset->buflen);

    return 0;
}

void iset_show(const Itemset *iset)
{
    size_t i;

    printf("%zu items:\n", iset->count);

    for (i = 0; i < iset->count; i++) {
        printf("[%d] %s (%zu letters)\n",
            i, iset->item[i].str, iset->item[i].length);
    }
}

void iset_free(Itemset *iset)
{
    if (iset) {
        free(iset->buf);
        free(iset->item);
    }

    memset(iset, 0, sizeof(*iset));
}

客户端代码看起来会更整洁:

int main()
{
    Itemset iset;

    if (iset_init(&iset, 50, 500) < 0) {
        fprintf(stderr, "Couldn't initialise dict.");
        exit(1);
    }

    iset_add(&iset, "Test");
    iset_add(&iset, "Tests");
    iset_add(&iset, "Tester");
    iset_add(&iset, "Testing");

    iset_show(&iset);    
    iset_free(&iset);

    return 0;
}

【讨论】:

    猜你喜欢
    • 2021-09-17
    • 2021-12-10
    • 1970-01-01
    • 2018-02-01
    • 1970-01-01
    • 2022-01-07
    • 2021-06-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多