从函数返回的字符串数组不按预期工作

时间:2015-08-05 12:01:18

标签: c string pointers

我正在尝试将一个字符串数组传递给一个函数,在该函数中对它进行一些更改,然后将其传递回main()并打印它以查看更改。它没有按预期工作。请告诉我哪里出错了。

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

//don't forget to declare this function
char** fun(char [][20]);

int main(void)
{
    char strar[10][20] = { {"abc"}, {"def"}, {"ghi"}, {""},{""} }; //make sure 10 is added
    char** ret; //no need to allocate anything for ret, ret is just a placeholder, allocation everything done in fun
    int i = 0;

    ret = fun(strar);
    for(i=0;i<4;i++)
        printf("[%s] ",ret[i]);

    printf("\n");
    return 0;
}

//don't forget function has to return char** and not int. (Remember char**, not char*)
char** fun(char strar[][20])
{
    int i = 0;
    char** ret;
    ret = malloc(sizeof(void*)); //sizeof(void*) is enough, it just has to hold an address 

    for(i=0;i<5;i++)
    {
        ret[i] = malloc(20 * sizeof(char));
        strcpy(ret[i],strar[i]);
    }

    strcpy(ret[3],"fromfun");

    return ret;
}

2 个答案:

答案 0 :(得分:6)

我可以看到的主要问题是内存溢出。

您分配内存以容纳一个元素

 ret = malloc(sizeof(void*));

但是,你要放5个元素。

for(i=0;i<5;i++)
{
    ret[i] = malloc(20 * sizeof(char));....

undefined behaviour。 超出分配的内存访问。

ret的内存分配应该是

 ret = malloc(5 * sizeof(char *));

 ret = malloc(5 * sizeof*ret); //portable

详细说明所做的更改

  • 分配5倍于单个元素的大小,因为我们将存储5个元素。
  • 严格来说,由于ret的类型为char **,我们需要在计算要为char *分配的大小时使用ret,而不是void * }}。
  • 使用sizeof *ret的变化使代码更加健壮,将来如果ret的类型更改为其他类型,您不需要重复类型更改在此分配中,无论如何,分配将取决于*ret的类型。

注意:FWIW,只有在参数为数据类型的情况下才需要sizeof参数的括号,如sizeof(int)。如果使用变量名作为参数,则括号是可选的,即sizeof(*ptr)sizeof *ptr都是完全有效且合法的。

那就是说,

  1. 在使用返回的指针
  2. 之前,请务必检查malloc()是否成功
  3. C中,sizeof(char)保证为1。使用相同的乘数是多余的。

答案 1 :(得分:5)

您需要确保为 ret 数组分配完整的指针数组。

//don't forget function has to return char** and not int. (Remember char**, not char*)
char** fun(char strar[][20])
{
 int i = 0;
 char** ret;
 ret = malloc(sizeof(void*) * 5); //sizeof(void*) is enough, it just has to hold an address 

 for(i=0;i<5;i++)
 {
  ret[i] = malloc(20 * sizeof(char));
  strcpy(ret[i],strar[i]);
 }

 strcpy(ret[3],"fromfun");

 return ret;
}