我想做这样的事情:
#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;
}
但我做不到,有时会打印一些奇怪的字符。。。
谢谢你的回复,我现在很理解了,但我陷入了问题的另一边。我没有准确地写出我的用例,所以我对它进行了编辑以使其完整。
这段代码中最明显的错误是:
- 将
myfunction
隐式声明为int myfunction();
- 指针的常量不正确
- 未为
main()
提供返回值
将myfunction
隐式声明为int myfunction();
这很容易解决,当这种情况发生时,编译器应该大声地对您咆哮。作为C的遗留特性,当遇到函数调用时,无论是原型还是定义,都没有已知的形式声明,则假设函数返回int
并接受可变数量的参数。因此,在main()
中,您的调用被假定为对如下函数的调用:
int myfunction();
稍后,当遇到realmyfunction
时,编译器至少应该向您发出警告,说明声明与预期类型不匹配(因为此时它认为它是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 : %sn", result, result);
return 0;
}
void myfunction(const char** in)
{
const char* test = "mytest";
printf("in myfunction() %p : %sn", test, test);
*in = test;
}
输出(因实施而异)
in main() 0x8048580 : mytest
in myfunction() 0x8048580 : mytest
现场观看。
我觉得不错。我可以建议给它一个原型,或者把你的myfunc()
定义移到main()
之前。同时在声明结果时为其赋值。这将使您更好地了解如果函数没有按您的期望执行,会发生什么。
由于某种原因,其他答案只是指出了错误的技术细节,但没有注意到真正的错误:您正在返回堆栈上数组的地址。但是当函数返回时,访问该数组将变成未定义的行为。其他代码可能会自由地覆盖内存,在内存中留下最糟糕的垃圾,或者相反,在返回的指针后面写入内存可能会丢弃代码中其他完全不连接部分的任何至关重要的变量。
如果要返回指针,则必须返回指向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