C 返回字符指针数组

C 返回字符指针数组,c,pointers,C,Pointers,我试图将char*数组返回给函数。我已经将代码简化为一个测试用例,该测试用例克隆了一个char数组,该数组不包含char,而是包含指向这些char的指针 /* * code.c */ #include <stdio.h> char* makePointerCopy(char cIn[]); int main() { char cTest[] = {'c', 't', 's', 't'}; char* cPTest[] = makePointerCopy(cTe

我试图将
char*
数组返回给函数。我已经将代码简化为一个测试用例,该测试用例克隆了一个char数组,该数组不包含char,而是包含指向这些char的指针

/*
 * code.c
 */
#include <stdio.h>

char* makePointerCopy(char cIn[]);

int main() {
    char cTest[] = {'c', 't', 's', 't'};
    char* cPTest[] = makePointerCopy(cTest);
    printf("%p %c", cPTest, *cPTest);
    fflush(stdout);
    return 0;
}

char* makePointerCopy(char cIn[]) {
    char* cOut[sizeof(cIn)/sizeof(cIn[0])];
    int iCntr;

    for (iCntr = 0; iCntr < sizeof(cIn)/sizeof(cIn[0]); iCntr++)
        cOut[iCntr] = cIn + iCntr;

    return cOut;
}
/*
*代码c
*/
#包括
char*makePointerCopy(char-cIn[]);
int main(){
字符cTest[]={c',t',s',t'};
char*cPTest[]=makePointerCopy(cTest);
printf(“%p%c”,cPTest,*cPTest);
fflush(stdout);
返回0;
}
char*makePointerCopy(char cIn[]{
char*cOut[sizeof(cIn)/sizeof(cIn[0]);
国际中心;
对于(iCntr=0;iCntr
撇开几个警告不谈,以下是编译器对该代码段的看法:

无效的初始值设定项(位于
char*cPTest[]=makePointerCopy(cTest);


为什么会发生这种情况?

因为
makePointerCopy
返回的是
char*
,而不是
char*[]

您应该能够将该行更改为:

char* cPTest = makePointerCopy(cTest);
更具体地说,您得到该错误消息的原因,而不是类型,是数组初始值设定项必须是编译时常量

即使声明没有存档 范围,则在C90和 和C99。C90需要编译时间 自动测试的常量初始值设定项 和寄存器阵列。C90和 C99要求创建一个字符数组 初始化为a)字符串文字, 或b)括号内的初始值设定项 名单


但是,类型不匹配是这里的实际问题。

您需要返回
char**
char*[]

特别是,如果您希望
makePointerCopy
返回“一个
char*
数组,那么您需要实际返回这样一个数组。现在您正在返回一个指向
char
或“
char*
”的指针


有问题的代码行正在尝试分配
makePointerCopy
的结果,它将
char*
返回给
char*[]
。虽然在C语言中这在技术上是可以的,而且编译器仍然会生成一个结果,但编译器基本上是在告诉您它生成的结果实际上可能不会像您期望的那样执行。

在这一行,您正试图将char*分配给char*数组。简单地说,它们是不同的类型。

因为您的函数返回的是
char>*
当您将其分配给
char*[]
时,C可能有一个非常弱的类型系统,但有些事情不应该做:-)

函数返回一个char*而不是char[]*.

char*
是一个指向单个字符的指针,根据需要,
char**
是指向数组的指针或
char*
让我们从警告开始。您声明:

char* cPTest[]
在英语中:“
cPTest
是指向char的指针数组”

英文版:“
makePointerCopy()
获取字符数组并返回指向字符的指针”

因此,您正在尝试将“指向字符的指针”分配给“指向字符的指针数组”。您看到问题了吗?我建议在执行分配之前仔细检查类型

也就是说,您真正想要的是声明
makePointerCopy()
以返回“指向char的指针的指针”:

因为,最后,您将返回指向返回数组的第一个元素的指针

另一个要点是:您将“cOut”声明为函数的局部变量

char* makePointerCopy(char cIn[]) {
    char* cOut[sizeof(cIn)/sizeof(cIn[0])];

    ...  /* cOut can ONLY be used within the function! */

    return cOut;  // <-- The address returned point to a 
                  //     block of memory that is no longer valid
                  //     after the end of the function
}
请注意,在返回此类值时必须严格遵守规则


作为一种替代方法,您可以使用
malloc()
分配所需的空间,只要您在不再需要它时记得
free()
它。

所有其他答案都是正确的,但您的代码似乎还有很多其他问题:

char* cOut[sizeof(cIn)/sizeof(cIn[0])];
我相信您认为sizeof(cIn)返回cIn数组中元素占用的内存量。这是错误的。在这种情况下,sizeof(cIn)将返回系统上指针的大小,通常为4或8字节。sizeof(cIn[0])将返回一个字符的大小,即1字节。通常无法在C中发现数组的大小,因此恐怕您必须将该大小传递给函数


还请记住,makePointerCopy返回指向静态分配内存块的指针。该内存基本上是makePointerCopy的一个局部变量,在makePointerCopy完成其工作后将被释放。换句话说,makePointerCopy将返回指向无效内存的指针。

还有一个重要问题此代码:
char*cOut[sizeof(cIn)/sizeof(cIn[0]);
将不起作用。参数列表中简单的
char-cIn[]
将不包含数组的大小信息。您需要类似于
template…(char(&cIn)[N]的内容)
,则N将匹配元素的数量。可选方法:使用
char*start,char*end
传递数组。如果我将iSize传递给函数,将其放在
makePointerCopy
调用之前的main()块中也会起作用吗?
int-iSize=sizeof(cTest)/sizeof(cTest[0]);
所以我需要更改返回类型?我应该将其更改为什么?我尝试了
char*[]
但这会产生大量的错误和警告。Pieter-请参阅我的答案,以获取更改内容的示例。如果我没记错的话,char**应该这样做。将cPTest的类型也更改为char**。我想我已经开始了解它了。至于局部变量:cOut指向一个未在
makePointerCopy
中生成的变量,因此我应该是安全的,对吧?在任何情况下,有没有办法防止C删除特定的局部变量?你是不安全的,因为cOut是在函数中声明的,在返回后使用它是无效的。你可以将它声明为“static”以允许返回它的地址。我将编辑a
char* makePointerCopy(char cIn[]) {
    char* cOut[sizeof(cIn)/sizeof(cIn[0])];

    ...  /* cOut can ONLY be used within the function! */

    return cOut;  // <-- The address returned point to a 
                  //     block of memory that is no longer valid
                  //     after the end of the function
}
char* makePointerCopy(char cIn[]) {
    static char* cOut[sizeof(cIn)/sizeof(cIn[0])];

    ...  /* cOut will survive the end of the function */

    return cOut;  // <-- The address can be returned 
}
char* cOut[sizeof(cIn)/sizeof(cIn[0])];