2010-01-22 165 views
4

我试图将一个char*的数组返回给一个函数。我简化了我的代码到一个测试用例,该用例克隆了一个char数组,而不是包含chars的指针指向这些chars。返回一个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; 
} 

一对夫妇的警告放在一边的,这就是编译器必须说这个代码片段:

无效初始化(在char* cPTest[] = makePointerCopy(cTest);

为什么会出现这种情况?

+1

此代码还有另一个重要问题:'char * cOut [sizeof(cIn)/ sizeof(cIn [0])]];'不起作用。参数列表中的简单'char cIn []'不会包含数组的大小信息。你需要类似'template ...(char(&cIn)[N])',那么N将匹配元素的数量。可选:使用'char * start,char * end'来传递数组。 – gimpf 2010-01-22 15:28:10

+0

如果我将iSize传递给函数,那么在makePointerCopy调用之前会把这个放在main()块中吗? 'int iSize = sizeof(cTest)/ sizeof(cTest [0]);' – Pieter 2010-01-22 15:35:01

回答

5

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

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

char* cPTest = makePointerCopy(cTest); 

更具体地说,你会得到错误信息,而不是一些关于类型的原因,就是数组的初始化需要在编译时常量。

http://bytes.com/topic/c/answers/215573-invalid-initializer

即使声明是无法以文件 范围,它会在这两个C90 和C99是非法的。 C90需要编译时间 用于自动 和寄存器阵列的常量初始化程序。并且C90和 C99都要求字符数组为 ,使用a)字符串文字 或b)括号括起来的初始化程序 列表进行初始化。

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

2

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

特别是如果你想makePointerCopy返回“的char*数组,那么你需要真正回归这样的阵列。现在你返回一个指向char,或” char*”。

线有问题的代码试图分配makePointerCopy的结果,该结果返回char*char*[]虽然在技术上C是可以的,并且编译器仍然会产生一个结果,但编译器基本上告诉你它产生的结果可能不是实际上按照你的预期执行。

3

在那l ine,你正试图给一个char *数组赋一个char *。简而言之,它们是不同的类型。

+0

所以我需要改变返回类型?我该如何改变它?我试过'char * []'但是会产生大量的错误和警告。 – Pieter 2010-01-22 15:29:38

+0

Pieter - 请参阅我的答案,了解要更改的示例。 – danben 2010-01-22 15:32:32

+0

char **应该这样做,如果我没记错的话。将cPTest的类型也更改为char **。 – Aaron 2010-01-22 15:37:25

2

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

0

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

0

char *是一个指向单个字符在那里,因为你需要char **这是一个指向数组的指针或char *

2

让我们先从警告。您宣布:

char* cPTest[] 

英文: “cPTest是数组的指针为char

char* makePointerCopy(char cIn[]); 

英文:“makePointerCopy()需要字符,并返回数组一个指向字符的指针

所以你试试将“指针指向字符”分配给“指向字符的指针数组”。你能看到问题吗?我建议在做任务之前仔细检查类型。

这就是说,你真正想要的是声明makePointerCopy()一个“指针的指针为char”回归:

char **makePointerCopy(char cIn[]); 

,因为在最后,你将指针返回的第一个元素返回数组。

另一个重点:你声明你“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 
} 

请记住,一旦函数终止,局部变量会自动失效。为了“保护”它,你可以声明它static

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 
} 

请注意,您必须遵守纪律时返回这种类型的值。

作为一种替代方案,只要您不再需要它,您就可以记住free(),您可以使用malloc()来分配需要的空间。

+0

我想我开始明白了。至于局部变量:cOut指向一个不是在'makePointerCopy'中产生的变量,因此我应该是安全的,对吧?无论如何,有没有办法让C擦除特定的局部变量? – Pieter 2010-01-22 15:54:47

+0

你不安全,因为cOut *在函数内被声明,并且在返回后无效使用它。您可以将其声明为“静态”以允许返回其地址。我要编辑答案来展示这一点。 – 2010-01-22 16:11:26

1

所有其他的答案是正确的,但似乎有相当多的其他问题与您的代码:

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

我相信你想的sizeof(CIN)返回的内存占用量cIn数组中的元素。这是不正确的。在这种情况下,sizeof(cIn)将返回系统上指针的大小,通常为4或8个字节。 sizeof(cIn [0])将返回一个字符的大小,即1个字节。通常没有办法在C中发现数组的大小,所以恐怕你必须将这个大小传递给你的函数。

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