我是C的新手,我花了2个小时才弄明白这个问题。
bridgeCheckRooms
虽然void helper(char* a, char* b){
a = malloc(strlen(b));
memcpy(a, b, strlen(b));
printf("%s %s\n", a, b);
}
int main(){
char* b = "hello";
char* a;
helper(a, b);
printf("%s", a);
}
始终是a
。我错过了什么吗?
答案 0 :(得分:4)
在main()
中,a
和b
是指针。
helper(a, b);
会将a
指针的副本和指针b
的副本提供给helper()
,作为helper()
调用的一部分。
该功能完成。
呼叫a
未更新/更改main()
中的helper(a, b)
。 b
都没有改变。
代码需要一种新方法,其中有几种很好的方法。示例:使用helper2()
的返回值。
char *helper2(const char *source);
int main(void) {
const char* b = "hello";
char* a = helper2(b);
printf("<%s>", a);
free(a);
}
现在创建helper2()
。代码模板如下:
#include <...> // whats includes are needed.
#include <...>
char *helper2(const char *source) {
size_t size_needed = ....; // length + 1 for the null character
char *destination = ...' // allocate
if (destination ...) { // Successful allocation?
memcpy(destination, ...., ...); // copy - include null character
}
return ... // What should be returned here?
}
答案 1 :(得分:3)
您错过了main()
按值a
将helper()
副本传递给a
的事实。因此helper()
中的a
是一个完全不同的变量(即使你给它的名字相同) - 它有不同的地址。
因此helper()
中a
的更改不会影响main()
中的helper()
。
无论main()
做什么,a
都表现出未定义的行为。 helper()
未初始化,因此将其值传递给printf()
会产生未定义的行为。将其传递给printf()
会出于同样的原因而给出未定义的行为。
helper()
中的%s
调用也有未定义的行为,因为printf()
会导致'\0'
期望字符串被memcpy()
终止,但是a
1}}调用没有将此类内容复制到printf()
。实际上,a
可能会继续从a
步进到随机存储器,直到找到一个零值的字节。这可能导致垃圾输出或(如果内存中没有这样的字节)模糊的程序崩溃。
您的代码的部分修复方法是将helper()
中的main()
更改为/* Danger: This code still has undefined behaviour */
void helper(char **a, char* b)
/* note usage of extra * on every usage of a in this function */
{
*a = malloc(strlen(b));
memcpy(*a, b, strlen(b));
printf("%s %s\n", *a, b);
}
int main()
{
char* b = "hello";
char* a;
helper(&a, b); /* note use of ampersand here */
printf("%s", a);
free(a); /* a has been malloc()ed, so free() it */
/* using a here will give undefined behaviour, since it is free()d */
}
。例如;
a
此代码通过使用指针对helper()
main()
中的%s
进行了更改{/ 1}}。
此部分修复代码的问题是printf
仍然导致a
期望'\0'
以尾随memcpy()
终止,但'\0'
不复制这样的尾随printf()
。因此helper()
次调用(main()
和helper()
)仍有未定义的行为。
要解决此问题,我们需要将void helper(char **a, char* b)
{
*a = malloc(strlen(b) + 1);
memcpy(*a, b, strlen(b) + 1);
printf("%s %s\n", *a, b);
}
更改为
b
分配一个更大的缓冲区,并将'\0'
的内容复制到其中包含strcpy()
。{/ p>
另一种方法是使用memcpy()
代替void helper(char **a, char* b)
{
*a = malloc(strlen(b) + 1);
strcpy(*a, b);
printf("%s %s\n", *a, b);
}
。
strcpy()
唯一的区别是'\0'
复制字符,直到它在b
中找到尾随SELECT id
, SUM(date < UNIX_TIMESTAMP()) AS BeforeNow
, SUM(date > UNIX_TIMESTAMP()) AS AfterNow
FROM tbl
WHERE status = 0
GROUP BY id;
。
答案 2 :(得分:1)
你没有更改功能内部。当你把malloc收到一个新地址时。
void helper(char **a, char *b){
*a = malloc(strlen(b)+1); //+1 for the \0 in the end of b
strcpy(*a, b);
printf("%s %s\n", *a, b);
}
int main(void){
char *b = "hello";
char *a;
helper(&a, b);
printf("%s\n", a);
}
在你的代码中你没有使用免费..你必须释放你做过malloc的所有指针...
所以在主页的末尾添加free(a)
。
答案 3 :(得分:0)
我重命名变量,要清楚。 @chux所说的是变量&#39; a&#39;改变了,但是变量&#39; x&#39; - 不是。
void helper(char* a, char* b){
a = malloc(strlen(b));
memcpy(a, b, strlen(b));
printf("%s %s\n", a, b);
}
int main(){
char* y = "hello";
char* x;
helper(x, y);
printf("%s", x);
}
UPD:这是原始代码。我只是重命名变量以消除变量命名的歧义,并更清楚地做解释。问题,正如@chux指出的那样,变量x由值发送,因此无法在函数main中更改。
答案 4 :(得分:0)
我看到的第一个错误是你曾经分配过strlen(foo)+1。复制字符串的正确大小是这个。比调用strcpy()或memset +1。但是对于字符串,我曾经在脑海中使用strcpy()更具性能:
char *strcpy(char *a , const char*b)
{
while(*a++=*b++)
;
return a;
}
然后(这是一个非常简单的版本,真正的版本有更多的检查)
char * memcpy(a,b,n)
{
while(n--)
*a++=*b++;
return a;
}
还有一个减少的计数器;使用memset,您还可以调用strlen()获取长度,然后添加一个。使用strcpy()不是必需的。所以,是的,差异并不明显,但有,但可以理解的是可重复性,代码的清晰度(teorethical,除非一些编译器优化)更好的性能