我想做那样的事情:
#include <stdio.h>
char * myfunction(char * in);
void myfunction2(char * in, const char ** content);
int main(){
char * name="aName";
char * result = myfunction(name);
return 0;
}
char * myfunction(char * in) {
const char *test = NULL;
myfunction2(in, &test);
return test; // I would like to return the value of test
}
void myfunction2(char * in, const char ** content) {
char input[1024];
//do some stuff to fill input
*content = input;
}
但是我无法做到,有时会打印一些奇怪的字符......
感谢您的回复,我现在理解得很清楚,但我仍然困在我问题的另一面。我没有准确写出我的用例,因此我将其编辑为完整。
答案 0 :(得分:3)
此代码中最明显的错误是:
myfunction
为int myfunction();
main()
隐含声明myfunction
为int myfunction();
这很容易解决,当发生这种情况时,你的编译器应该大声咆哮大声。作为C的遗留特性,当遇到函数调用时,无法通过原型或定义进行正式声明,假定函数返回int
并接受可变数量的参数。因此,在main()
中,您的调用假定为一个如下所示的函数:
int myfunction();
稍后遇到真正的 myfunction
时,编辑器应该至少尖叫你,警告声明如何与预期的类型不匹配(因为此时它认为这是int myfunction()
)。然而,即使这样,呼叫仍然应该通过,但依靠这一点是可怕的做法。在使用前正确地对您的功能进行原型设计。
所有指针的数据类型都不正确。
函数中的字符串文字未绑定到本地数组空间。它是一个只读数据缓冲区,位于程序数据块中的某个只读段中。正确的声明是:
const char *test = "mytest";
但这会产生连锁效应,需要更改此代码的其余部分,您将在稍后看到。
没有为main()
在main()
的结论中明确。显然C99允许你跳过这个并且实现假设为你返回0。不要给他们那种快乐;抓住它自己。
解决上述所有问题......
#include <stdio.h>
void myfunction(const char** in);
int main()
{
const char *result = NULL;
myfunction(&result);
printf("in main() %p : %s\n", result, result);
return 0;
}
void myfunction(const char** in)
{
const char* test = "mytest";
printf("in myfunction() %p : %s\n", test, test);
*in = test;
}
输出(因实施而异)
in main() 0x8048580 : mytest
in myfunction() 0x8048580 : mytest
答案 1 :(得分:0)
对我来说很好看。我可以建议在myfunc()
之前给它一个原型或移动main()
定义。在声明时也为结果赋值。如果函数没有达到你期望的效果,那么这将让你更好地了解正在发生的事情。
答案 2 :(得分:0)
出于某种原因,其他答案只是指出了错误的技术细节,但没有注意到错误的原因:你正在返回堆栈中数组的地址。但是当函数返回时,访问该数组将成为未定义的行为。其他代码可以自由地覆盖内存,在其中留下最坏的垃圾,或者相反,写入返回指针后面的内存可能会丢弃代码中其他一些完全未连接的部分的重要变量。
如果要返回指针,则必须返回指向static
对象的指针,或者必须返回指向堆上某些内容的指针。以下是static
案例:
char* foo() {
static char staticArray[1024];
return staticArray;
}
在此使用static
可确保在程序执行期间为staticArray []保留的内存将保留给它。然而,这有三个缺点:
数组大小在编译时固定
这通常不是多线程安全的,因为所有线程都将使用相同的全局分配内存
您通常不能指望返回指针后面的数据在函数调用中保持不变。请考虑以下代码:
void bar() {
char* temp = foo();
temp[0] = 7;
}
void baz() {
char* temp = foo();
temp[0] = 3;
bar();
//now temp[0] is 7 !
}
在某些罕见的情况下,这可能是理想的,但大多数情况下并非如此。
所以,如果你想能够自由地使用返回指针后面的内存,你必须为malloc()
内存(当然,free()
之后)。像这样:
char* foo(int size) {
return malloc(size);
}
void baz() {
char* sevenBytes = foo(7);
//Do something with seven bytes
free(sevenBytes);
}
void bar() {
char* threeBytes = foo(3);
threeBytes[0] = 3;
baz();
assert(threeBytes[0] == 3); //baz() worked on it's own memory
free(threeBytes);
}
在字符串处理的情况下,POSIX-2008标准中有许多方便的功能可以为您进行内存分配,其中包括strdup()
和asprintf()
。以下是一些使用示例:
int main() {
char* hello = strdup("Hello");
char* greeting;
if(0 > asprintf(&greeting, "%s World!\nMemory for hello was allocated at %llx", hello, (long long)hello)) {
//error handling
}
printf(greeting);
free(hello);
free(greeting);
}
这将打印如下内容:
Hello World!
Memory for hello was allocated at c726de80