char * myFunction () {
char sub_str[10][20];
return sub_str;
}
void main () {
char *str;
str = myFunction();
}
错误:从不兼容的指针类型返回
感谢
答案 0 :(得分:12)
C中的字符串数组可以与char**
或char*[]
一起使用。但是,您无法返回存储在堆栈中的值,就像在函数中一样。如果要返回字符串数组,则必须动态保留它:
char ** sub_str = malloc(10 * sizeof(char*));
for (int i =0 ; i < 10; ++i)
sub_str[i] = malloc(20 * sizeof(char));
/* Fill the sub_str strings */
return sub_str;
然后,main可以像这样得到字符串数组:
char** str = myFunction();
printf("%s", str[0]); /* Prints the first string. */
答案 1 :(得分:6)
对于刚开始的程序员来说,&#34; stack&#34;或者#34;堆&#34;可能有点令人困惑,特别是如果你已经开始使用Ruby,Java,Python等更高级别的语言进行编程。
考虑:
char **get_me_some_strings() {
char *ary[] = {"ABC", "BCD", NULL};
return ary;
}
编译器将正确地发出关于尝试返回局部变量的地址的投诉,并且您肯定会在尝试使用返回的指针时遇到分段错误。
和
char **get_me_some_strings() {
char *ary[] = {"ABC", "BCD", NULL};
char **strings = ary;
return strings;
}
会关闭编译器,同时仍然会遇到同样令人讨厌的分段错误。
为了让除了狂热者之外的所有人都感到高兴,你会做一些更精细的事情:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char **get_me_some_strings() {
char *ary[] = { "ABC", "BCD", NULL };
char **strings = ary; // a pointer to a pointer, for easy iteration
char **to_be_returned = malloc(sizeof(char*) * 3);
int i = 0;
while(*strings) {
to_be_returned[i] = malloc( sizeof(char) * strlen( *strings ) );
strcpy( to_be_returned[i++], *strings);
strings++;
}
return to_be_returned;
}
现在使用它:
void i_need_me_some_strings() {
char **strings = get_me_some_strings();
while(*strings) {
printf("a fine string that says: %s", *strings);
strings++;
}
}
请记住在完成后释放已分配的内存,因为没有人会为你做这件事。这适用于所有指针,而不仅仅是指向指针的指针! (我想)。
为了更好地理解这一切,您可能还想阅读:What and where are the stack and heap?
答案 2 :(得分:2)
原因:
您需要返回类型为char(*)[20]
。但即使在这种情况下,您也不希望从函数返回指向本地对象的指针
这样做:
使用malloc分配sub_str,并返回char**
。
答案 3 :(得分:1)
编译器错误的原因很简单,但不能解决您真正想要做的事情。您声明该函数返回char *,同时返回char **。
在不知道你正在做什么的细节的情况下,我将假设以下两件事之一:
1)该函数的目的是创建并返回一个字符串数组。 2)该函数对字符串数组执行一些操作。
如果#1为真,你需要几个malloc调用才能完成这项工作(实际上只需要两个,但为了简单起见,我会使用几个)。
如果您不知道数组应该有多大,那么您的函数声明应如下所示:
char ** allocateStrings ( int numberOfStrings, int strLength );
原因是因为你实际上是在返回一个指针数组的指针,你需要知道每个字符串有多少字符串和多长时间。
char ** allocateStrings ( int numberOfStrings, int strLength )
{
int i;
//The first line is allocating an array of pointers to chars, not actually allocating any strings itself
char ** retVal = ( char ** ) malloc ( sizeof ( char * ) * numberOfStrings );
//For each string, we need to malloc strLength chars
for ( i = 0; i < numberOfStrings; i ++ )
{
//Allocate one extra char for the null pointer at the end
retVal [ i ] = ( char * ) malloc ( sizeof ( char ) * ( strLength + 1 ) );
}
return retVal;
}
正如其他人所指出的那样,最好的做法就是分配也可以解除分配。因此需要一个清理功能。
void cleanupStrings ( char ** strArray, int numberOfStrings )
{
int i;
for ( i = 0; i < numberOfStrings; i ++ )
{
//Should be checking to see if this is a null pointer.
free ( strArray [ i ] );
}
//Once the strings themselves are freed, free the actual array itself.
free ( strArray );
}
现在,请记住,一旦调用了清理函数,您就无法再访问该数组了。试图仍然使用它很可能会导致您的应用程序崩溃。
如果#2为真,那么你想分配字符串,处理字符串并清理它们。您应该使用上面的两个函数来分配/解除分配您的字符串,然后使用第三个函数来对它们做任何事情。
void processStrings ( char ** strArray, int numberOfStrings, int strLength );
答案 4 :(得分:1)
正如其他人正确地说你应该使用malloc
的动态内存分配来将你的数组存储在heap
中并返回指向其第一个元素的指针。
此外,我发现编写一个简单的array of string
实现很有用,它具有最小的数据操作API。
类型和API:
typedef struct {
char **array_ptr;
int array_len;
int string_len;
} array_t;
array_t* array_string_new(int array_len, int string_len);
int array_string_set(array_t *array, int index, char *string);
char* array_string_get(array_t *array, int index);
int array_string_len(array_t *array);
<强>用法:强>
它创建一个包含4个维度的数组,可以存储长度为4个字符的字符串。如果字符串长度超出指定的长度,则只存储其前4个字符。
int main()
{
int i;
array_t *array = array_string_new(4, 4);
array_string_set(array, 0, "foo");
array_string_set(array, 1, "bar");
array_string_set(array, 2, "bat");
array_string_set(array, 3, ".... overflowed string");
for(i = 0; i < array_string_len(array); i++)
printf("index: %d - value: %s\n", i, array_string_get(array, i));
/* output:
index: 0 - value: foo
index: 1 - value: bar
index: 2 - value: bat
index: 3 - value: ...
*/
array_string_free(array);
return 0;
}
<强>实施强>
array_t*
array_string_new(int array_len, int string_len)
{
int i;
char **array_ptr = (char**) malloc(array_len * sizeof(char**));
for(i = 0; i < array_len; i++) {
array_ptr[i] = (char*) malloc(string_len * sizeof(char));
}
array_t *array = (array_t*) malloc(sizeof(array_t*));
array->array_ptr = array_ptr;
array->array_len = array_len;
array->string_len = string_len;
return array;
}
int
array_string_set(array_t *array, int index, char *string)
{
strncpy(array->array_ptr[index], string, array->string_len);
return 0;
}
char*
array_string_get(array_t *array, int index)
{
return array->array_ptr[index];
}
int
array_string_len(array_t *array)
{
return array->array_len;
}
int
array_string_free(array_t *array)
{
int i;
for(i = 0; i < array->array_len; i++) {
free(array->array_ptr[i]);
}
free(array->array_ptr);
return 0;
}
请注意,这只是一个简单的实现,没有错误检查。
答案 5 :(得分:0)
正如其他人所说,你不能将一个本地char数组返回给调用者,并且必须使用堆内存。
但是,我不建议在函数中使用malloc()
。
好的做法是,无论谁分配内存,解除分配(并在malloc()
返回NULL时处理错误条件)。
由于myFunction()
无法控制它返回时分配的内存,因此让调用者提供存储结果的内存,并将指针传递给该内存。
这样,你的函数的调用者可以解除分配或重新使用内存(例如,对myFunction()
的后续调用),但他认为合适。
但要小心,要么就此类调用的固定大小达成一致(通过全局常量),要么将最大大小作为附加参数传递,以免最终覆盖缓冲区限制。
答案 6 :(得分:0)
我使用该函数将字符串拆分为字符串数组
char ** split(char *str, char *delimiter)
{
char *temp=strtok(str,delimiter);
char *arr[]={temp};
int i=0;
while(true)
{
elm=strtok (NULL, delimiter);
if(!temp) break;
arr[++i]=temp;
}
return arr;
}
答案 7 :(得分:-1)
首先,您不能返回存储在堆栈中的字符串变量,而需要使用malloc动态分配内存,此处给出了带有示例的datails 转到https://nxtspace.blogspot.com/2018/09/return-array-of-string-and-taking-in-c.html 得到正确答案
答案 8 :(得分:-3)
char *f()
{
static char str[10][20];
// ......
return (char *)str;
}
int main()
{
char *str;
str = f();
printf( "%s\n", str );
return 0;
}
您可以使用static而不是malloc。这是你的选择。