如何将字符串分配给char *指针?

时间:2016-12-16 00:22:28

标签: c arrays string pointers char

我是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。我错过了什么吗?

5 个答案:

答案 0 :(得分:4)

main()中,ab是指针。

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()按值ahelper()副本传递给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,除非一些编译器优化)更好的性能