首页 > 解决方案 > 如何将 char** 作为函数参数返回

问题描述

我有一个函数,它返回一个指向 chars ( char**) 指针的指针。该函数有 2 个参数

下面编写了一些示例代码(为简单起见,省略了大部分错误检查):

char** get_paths(int* num_paths, int* errno) {
    char* path1 = NULL;
    char* path2 = NULL;
    char** paths = NULL;

    if(errno == NULL) {
        printf("Set errno in case of error, but cannot dereference NULL pointer\n");
        goto exit;
    }

    path1 = calloc(1, strlen("foo") + 1);
    path2 = calloc(1, strlen("bar") + 1);

    strcpy(path1, "foo");
    strcpy(path2, "bar");

    *num_paths = 2;
    paths = calloc(1, *num_paths*sizeof(char *));
    paths[0] = path1;
    paths[1] = path2;

    *errno = 0;
exit:
    return paths;
}

int main(void) {
    char** paths = NULL;
    int num_paths = 0;
    int errno = 0;

    paths = get_paths(&num_paths, &errno);
    if(errno != 0) {
        return -1;
    }

    for(int i = 0; i < num_paths; i++) {
        printf("%s\n", paths[i]);
        free(paths[i]);
    }
    free(paths);
}

我遇到的问题是我无法设置错误代码,以防 NULL 指针作为errno. 您可能会争辩说这是一个用户错误,但我仍然想首先避免这种情况。

所以我的问题是:我是否可以重写我的get_paths函数,使其返回一个整数作为错误代码,但也可以char**通过函数参数返回 a 而无需诉诸char***以下示例:

int get_paths_3(char*** paths, int* num_paths) {
    char* path1 = NULL;
    char* path2 = NULL;

    path1 = calloc(1, strlen("foo") + 1);
    path2 = calloc(1, strlen("bar") + 1);

    strcpy(path1, "foo");
    strcpy(path2, "bar");

    *num_paths = 2;
    *paths = calloc(1, *num_paths*sizeof(char *));
    (*paths)[0] = path1;
    (*paths)[1] = path2;

    return 0;
}

标签: cpointerscharreturn-valuedynamic-memory-allocation

解决方案


这几乎是唯一可以使用“三星”指针的情况。在 API 设计中为错误代码保留返回值是相当普遍的做法,因此这种情况并不少见。

有替代品,但可以说它们并没有好多少。void*您可以滥用可以转换为/从的事实,char**但它并没有更漂亮且类型安全性更低:

// not recommended

int get_paths_4 (void** paths, size_t* num_paths)
{
    char* path1 = calloc(1, strlen("foo") + 1);
    char* path2 = calloc(1, strlen("bar") + 1);

    strcpy(path1, "foo");
    strcpy(path2, "bar");

    *num_paths = 2;
    char** path_array;
    path_array= calloc(1, *num_paths*sizeof(char *));
    path_array[0] = path1;
    path_array[1] = path2;
    *paths = path_array;
    return 0;
}

...

void* vptr;
size_t n;

get_paths_4 (&vptr, &n);
char** paths = vptr;

for(size_t i=0; i<n; i++)
{
  puts(paths[i]);
}

一个更合理的选择可能是将所有参数包装成一个struct类型并将该类型作为指针传递。


推荐阅读