c char *问题

时间:2011-03-15 08:39:27

标签: c char

这是一个绝对的noob问题,但我似乎没有在任何地方找到合适的答案,所以在这里,给出这个代码:

#include <stdio.h>
#include <stdlib.h>

void initialize( char * buffer)
{
    buffer = malloc(1);
    *buffer='a';
}


int main(void) {
    char * buff;
    buff = malloc(sizeof(char));
    *buff = 'b';
    initialize(buff);
    puts("Contents of buffer are: ");
    puts(buff);
    return 0;
}

main的输出总是'b',这对我来说真的很奇怪。我认为通过传递指针初始化我可以修改在main中声明的指针的值,但由于某种原因它似乎是通过值传递变量,并且在返回时我有在main中指定的值,因此'b' 。

我想知道为什么这个...我应该传递对指针的引用吗?像char *&amp; ??

此致 亚历

6 个答案:

答案 0 :(得分:5)

在您的功能中,您首先要使用新的buffer将内存中的其他位置重新分配给malloc。然后你修改这个新的内存位置,但主函数中的buff没有被修改,因为它仍然指向旧的位置。

如果删除malloc,它将起作用:

void initialize( char * buffer) {
    *buffer='a';
}

现在我们正在修改初始内存位置。

答案 1 :(得分:1)

您需要修改initialize()函数以获取指向缓​​冲区的指针并传入指针的地址。虽然它接收到您传入的缓冲区,但您无法更改buff指向的方式。请注意,在这种情况下您将发生内存泄漏,并且您无法将内容作为字符串打印,因为它未正确地终止。

void initialize(char **buffer)
{
    *buffer = malloc(sizeof(char));
    **buffer='a';
}

int main(void) {
    char *buff;
    buff = malloc(sizeof(char));
    *buff = 'b';
    initialize(&buff);
    puts("Contents of buffer are: ");
    printf("%c\n", *buff);
    return 0;
}

以下评论的答案:

  

我不明白为什么需要一个指向指针的指针......这就像C ++中的引用一样?

当我阅读您的代码时,我认为您想要更改buff变量(在main())指向的内容,即新缓冲区。当我看到你在initialize()函数中分配一个新的缓冲区时,我想。为了能够从不同的位置(或函数)更改变量的值,您需要该变量的地址。由于它最初是一个字符指针char *,因此您需要一个指向该字符指针的指针char **。是的,这就像C ++中的引用一样,只是更冗长。

  

所以我可以修改传递的变量的值吗?

如果您打算只修改传入的缓冲区的内容,Krtek会介绍它。您需要做的就是省略缓冲区的新分配并修改缓冲区指向的内容。

void initialize(char *buffer)
{
    /* *buffer = malloc(sizeof(char)); */ /* do not need this */
    /* modify the buffer that was passed in */
    *buffer='a';
}
  

关于内存泄漏问题

实际上,内存泄漏是由于在没有释放先前分配的内存的情况下分配新缓冲区引起的。你实际上有这个:

char *buff = malloc(sizeof(char)); /* allocate some memory */
buff = malloc(sizeof(char));       /* oops, memory leak */
  

你的意思是使用带有非空终止字符串的puts?这就是你使用printf(“%c \ n”,* buff)的原因吗?强制字符串以\ n?

结束

这是一个不同的问题。 puts()采用以null结尾的字符串,并将其打印到标准输出,后跟新行。打印潜在的垃圾文本不会是内存泄漏,它只是......其他的东西。您的缓冲区仅包含单个字符的空间(没有空终止符)。因此,不应使用puts()来打印缓冲区的内容。你应该只打印那个单个字符。 printf()'\n'的使用最终会产生与puts()相同的输出行为。

答案 2 :(得分:1)

如果首选没有内存泄漏的无错误代码段,这里有一些替代已发布的内容,更适用于现实世界中的编程。

请注意,mallocs应该也可以使用相同的“代码模块”。 不要在一个模块中使用malloc而在另一个模块中免费使用,这是非常糟糕的做法!

版本1:

#include <stdio.h>
#include <stdlib.h>

void set (char* buffer)
{
    *buffer='a';
}


int main (void)
{
    char* buff;

    buff = malloc(sizeof(char));  /* main allocates */
    *buff = 'b';

    set (buff);

    puts("Contents of buffer are: ");
    printf("%c", *buff);  /* don't use puts on single characters! */

    free(buff); /* main cleans up its own mess */
    return 0;
}

第2版:

/* main.c */
#include <stdio.h>
#include <stdlib.h>
#include "my_functions.h"


int main (void)
{
    char * buff;

    buff = malloc(sizeof(char));
    *buff = 'b';

    alloc_and_set (&buff);

    puts("Contents of buffer are: ");
    printf("%c", *buff);

    cleanup();
    return 0;
}

my_functions.h

#ifndef MY_FUNCTIONS_H
#define MY_FUNCTIONS_H

void alloc_and_set (char** buffer);
void cleanup (void);

#endif /* MY_FUNCTIONS_H */

my_functions.c

#include "my_functions.h"

static char* internal_buffer = NULL;  /* used to keep track of allocated data */

void alloc_and_set (char** buffer)
{
  if(internal_buffer == NULL)  /* make function memory leak proof */
  {
    internal_buffer = malloc(sizeof(char));
  }

  *internal_buffer = 'a';
  *buffer = internal_buffer;
}

void cleanup (void)
{
    free(internal_buffer);   /* my_functions module cleans up its own mess */
    internal_buffer = NULL;
}

答案 3 :(得分:0)

您将指针的副本修改为指向另一个位置,但您的真实指针并未指向它。 如果您不想使用此代码,请使用此功能。

void initialize( char ** buffer)
{
    *buffer = malloc(1);
    **buffer='a';
}

然后致电initialize(&buff);

答案 4 :(得分:0)

当你这样做时

buffer = malloc(1);

最初从main传递的缓冲区变量不受影响,因为它已通过值传递。

如果你这样写:

void initialize( char **buffer)
{
    *buffer = malloc(1);
    **buffer='a';
}

然后你会看到变化。

Edit1:您需要了解*运算符。 buffer本身就是一个指针。 * buffer实际上是缓冲区指向的位置,更改它实际上不会影响缓冲区。

答案 5 :(得分:0)

void initialize( char * buffer)
{

    // buffer is a local pointer to this function which will have 
    // same value as buff in main AT THIS POINT.

    // now you call malloc to allocate memory and make buffer
    // point to that memory. So the value of buffer got changed now.
    // buff in main remains unchanges.
    buffer = malloc(1);

    // now you write to the memory allocated.
    *buffer='a';

    // key point is buff in main is still pointing where it was.
}


int main(void) {

    // buff is now a wild pointer.
    char * buff;

    // now you allocate memory using malloc and make buff point to that memory.
    buff = malloc(sizeof(char));

    // you write to the memory pointed to by buff.
    *buff = 'b';

    // you pass buff BY VALUE to the function initilize.
    initialize(buff);

    // since a copy of buff (buffer) was changed, buff still points
    // to a memory that has b in it.
    puts("Contents of buffer are: ");
    puts(buff);
    return 0;
}

如果您希望被调用函数影响buff的值,则需要传递其地址:

void initialize( char ** buffer)
{
    *buffer = malloc(1);
    **buffer='a';
}

并将其命名为:

initialize(&buff);

但请注意,这会泄漏main中分配的内存。由于你已经在main中分配了内存,你可以删除malloc:

void initialize( char * buffer)
{
    *buffer='a';
}