【问题标题】:Modifying pointer array in C function在 C 函数中修改指针数组
【发布时间】:2015-06-21 22:56:18
【问题描述】:

我在处理 C 中的一维和二维动态分配数组时遇到了问题。我发现了类似的问题,但是没有一个对我有帮助,所以我要问一个新问题。

这是我的问题。使用下面的函数,我想将一个新元素添加到二维 char 数组中。大小不是问题,我在外面的某个地方增加。

void addElem(char ***tabs, int size, char *new) {
    *tabs[size] = (char*)malloc(sizeof(char)*strlen(new));
    *tabs[size] = new;
    *tabs = (char **)realloc(*tabs, size * sizeof(char *));
}

在代码中,函数是这样调用的:

int i;
char *tmp;
char **array = (char **)malloc(sizeof(char *));
//some stuff, also initializing i and tmp
addElem(&array, i, tmp);

问题是该函数即使分配了数据,它也不会在那里保存任何数据(例如,strcmp 使用 **array 给出 SIGSEGV)。在调试类似函数(管理一维整数数组)时,我发现它们实际上在这些函数内部正常工作,只是返回后数据没有保存。

我尝试显示尽可能少的代码,但如果有帮助,here 是完整代码(将 addElem 函数重命名为 dodajDoTablicySlow)。谢谢。

【问题讨论】:

  • 建议:1)不要投malloc()的返回值2)不要成为三星级程序员。
  • 您的strlen() 函数中的nowy 来自哪里?

标签: c arrays pointers


【解决方案1】:

考虑您的addElem() 函数:

void addElem(char ***tabs, int size, char *new) {
    *tabs[size] = (char*)malloc(sizeof(char)*strlen(nowy));
    *tabs[size] = new;
    *tabs = (char **)realloc(*tabs, size * sizeof(char *));
}

此函数不会在您认为的位置写入新元素。数组下标运算符([])的优先级高于间接运算符(*),所以*tabs[size]的意思是“数组tabs的元素size所指向的东西”,不是 em> "tabs指向的数组的元素size".

另外,如果size 是动态数组的当前大小——就像char * 成员的数量*tabs 有空间容纳——那么(*tabs)[size] 超出了它的容量。即使它请求足够的空间来包含该位置,但它没有,realloc() 调用也不会以任何方式保证扩展为*tabs 分配的内存以包含该空间。将新分配放在其他地方是完全免费的。当新尺寸大于旧尺寸时,有时可能需要这样做,但即使新尺寸更小,它也可以随意这样做。在某些时候,使用此函数可能会在重新分配时丢失数据。

此外,您的函数会泄漏内存。它malloc()s 空间几乎足以容纳全局变量nowy 指向的字符串,然后用函数参数new 覆盖指向该空间的唯一指针。

此外,您的函数没有很好的方法来发出失败信号。

这将是一个正确、安全、无泄漏的实现:

/*
 * Ensures that the dynamic array of char * pointed to by '*tabs' has
 * sufficient capacity for exactly 'size' + 1 elements, and stores the
 * value of 'el' at the last position.  Updates *tabs with a pointer to
 * the (possibly different) location of the enlarged array.  Returns the
 * location of the array, or NULL if memory allocation fails (in which
 * case '*tabs' is unchanged, and still a valid pointer to allocated memory).
 */
char **addElem(char ***tabs, size_t size, char *el) {
    char **newtabs = realloc(*tabs, (size + 1) * sizeof(char *));

    if (newtabs) {
        *tabs = newtabs;
        (*tabs)[size] = el;
    }

    return newtabs;
}

【讨论】:

  • 感谢您的解释!抱歉,我忘了说 - 大小不是问题,我只是在该函数之外增加它(不是最好的方法,但是当我增加函数内部的大小时,我不知道如何摆脱警告)。此外,还有我的另一个错误——我没有将 nowy 更改为 new。我会尽快修改,抱歉。
  • 恰恰相反,size 的问题之一。您的原始代码肯定至少写在realloc()ed 数组的范围之外,并且可能在起始分配的范围之外。在函数外增加size 与此无关。
  • 此外,仅将nowy 更改为new 仍然会导致内存泄漏。如果要复制字符串new 指向并将其分配给数组元素,请考虑使用strdup()。在这种情况下,请记住稍后需要释放该内存。
  • 旁注,但是如何回答问题的一个很好的例子。
【解决方案2】:

一个非常简单的关于三指针的程序:

#include <stdio.h>
void printElem(int ***tabs) {
    printf("%d\n",***tabs);

}
int main()
{
     printf("Hello, World!\n");
     int b = 7;
     int *d;
     int **t;
     d = &b;
     t = &d;
     printElem(&t);

     return 0;
}


output:
sh-4.3# main                                                                                                                                                                                                  
Hello, World!                                                                                                                                                                                                 
 7  

【讨论】:

    猜你喜欢
    • 2016-11-07
    • 1970-01-01
    • 2013-11-13
    • 2021-03-05
    • 1970-01-01
    • 2019-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多