C语言中的char *作为引用

9
如何将 char* 作为引用传递?
我的函数使用 malloc()
void set(char *buf)
{
    buf = malloc(4*sizeof(char));
    buf = "test";
}

char *str;
set(str);
puts(str);

C++程序员注意事项-在C++中,你应该使用指针的引用来完成这个操作:void set(char *& buf){ buf = malloc(5); strcpy(buf, "test"); }(函数体内buf左侧没有*)。这样你就不会意外地传递nullptr给函数了。 - Alexander Malakhov
7个回答

19
您需要传递指针的地址:
void set(char **buf)
{
    *buf = malloc(5*sizeof(char));
    // 1. don't assign the other string, copy it to the pointer, to avoid memory leaks, using string literal etc.
    // 2. you need to allocate a byte for the null terminator as well
    strcpy(*buf, "test");
}

char *str;
set(&str);
puts(str);

3
4个字符无法存储该字符串,尽管如此 :) 或许使用sizeof("test")会更好。 - Niklas B.
3
sizeof(char) 总是等于 1 - Jens Gustedt
1
@Kakashi:strlen在运行时计算(除非编译器足够聪明以进行优化)。 - Karoly Horvath
@Kakashi KarolyHorvath最后一条评论非常有价值:这将对性能产生很大影响。如果可以让编译器代劳,就不要在运行时做任何事情 ;) - Gewure
如果您遇到给 *buf 分配内存时语法不正确的问题,可以使用以下代码行: *buf = static_cast<char *>(malloc(LENGTH)); // 符合规范 - Sami Haroon
显示剩余2条评论

6
你需要将它作为指向指针的指针传递:
void set(char **buf)
{
    *buf = malloc(5 * sizeof(char));
    strcpy(*buf, "test");
}

这样调用:

char *str;
set(&str);
puts(str);
free(str);

请注意,我已经更改了malloc调用以分配五个字符,这是因为你只为实际字符分配空间,但字符串还包含一个特殊的终止字符,你需要为其留出空间。
我还使用了strcpy将字符串复制到分配的内存中。这是因为否则你会覆盖指针,意味着你会失去你所分配的指针,并且会有内存泄漏。
当你完成后,你应该记得free指针,否则内存将保持分配状态直到程序结束。

2
请解释为什么您使用了“5”而不是“4”。当我看到这个原帖时,我感到非常不舒服。 - D.Shawley

4

C语言不支持按引用传递。但是你可以传递指向指针的指针,并进行设置:

void set(char **buf)
{
    *buf = malloc(5*sizeof(char)); //5, to make room for the 0 terminator
    strcpy(*buf,"test"); //copy the string into the allocated buffer.
}

char *str;
set(&str);
puts(str);

在计算机科学中,按引用传递意味着传递一个变量的地址。C++创建了一个与计算机科学中常规定义不同的定义。这并不意味着C++的定义是常规定义,而且问题本来就是关于C的。在C中,按引用传递意味着通过指针传递。C11 6.2.5 指针类型可以从函数类型或对象类型派生,称为引用类型。指针类型描述了一个对象,其值提供对引用类型实体的引用。从引用类型T派生的指针类型有时称为“指向T的指针”。 - Lundin
通常我们区分按值传递和按引用传递,其中引用是隐式传递的。许多语言,如C语言,被认为只支持按值传递,但你可以通过显式地传递指向所需引用的指针来模拟按引用传递。(尽管该指针是按值传递的)因此,我不同意你的定义。 - nos
尽管你不同意,但这并不是我的定义,而是C标准中对C语言引用的定义。在OP的例子中,buf是char类型的引用。引用本身被按值传递这一事实是另外一回事。 - Lundin

3

在 C 语言中,没有引用类型。如果需要传递指向指针的指针,你需要使用 char**

void set(char** buf)
{
    *buf = malloc(5); /* 5, not 4: one for null terminator. */
    strcpy(buf, "test");
}

请注意:
buf = "test";

该代码不会将"test"复制到buf中,而是将buf指向字符串字面值"test"的地址。要进行复制,请使用strcpy()

记得在不再需要时free()返回的缓冲区:

char* str;
set(&str);
puts(str);
free(str);

在计算机科学中,“按引用传递”意味着传递一个变量的地址。C++已经创建了一个与计算机科学中通常定义不同的定义。这并不意味着C++定义就是通常规定的,而且这个问题本来就是关于C语言的。在C语言中,“按引用传递”表示通过指针传递。C11 6.2.5 指针类型可以由函数类型或对象类型派生而来,称为引用类型。指针类型描述的是一个对象,其值提供对引用类型实体的引用。有时将从引用类型T派生的指针类型称为“指向T的指针”。 - Lundin

1
在上面由 hmjd 给出的示例中,应该是这样的:
strcpy(*buf, "test");

1

C语言是按值传递的,没有按引用传递。


在计算机科学中,按引用传递意味着传递一个变量的地址。C++创建了一个与计算机科学中常规定义不同的定义。这并不意味着C++的定义是常规定义,而且问题本来就是关于C的。在C中,按引用传递意味着通过指针传递。C11 6.2.5 指针类型可以从函数类型或对象类型派生,称为引用类型。指针类型描述了一个对象,其值提供对引用类型实体的引用。从引用类型T派生的指针类型有时称为“指向T的指针”。 - Lundin
@Lundin你有“在计算机科学中,按引用传递意味着传递一个变量的地址”的参考资料吗?据我所知,“按引用传递”及其同义词自Fortran和Pascal以来就已经被用于它们当前的含义,比C++更早。 - Joni
我认为我们可以达成共识,在计算机科学中,通常只有传值或传引用两种方式。C和C++支持一种原始的传引用方式,称为指针,它允许您修改实际的引用地址。但这个特性并不妨碍指针参数被视为传引用。在C++中,他们决定创建一种传引用的替代语法,即C++引用类型。此后,C++程序员开始相信指针语法不再是传引用了。别问我为什么。 - Lundin
确实,指针本身是按值传递的,它在堆栈/寄存器中分配。同样,C++引用也是如此!生成的机器代码是相同的。 - Lundin
@Lundin 关于“我认为在计算机科学中,通常只有传值和传引用这两种方法”,我不同意;存在许多其他(虽然较不常见)的传递参数策略。请参见例如 http://en.wikipedia.org/wiki/Evaluation_strategy - Joni

0

C语言不能通过引用传递函数参数,C总是通过值传递它们。

来自Kernighan和Ritchie:

(K&R第2版,1.8 调用按值传递) "在C中,所有函数参数都是按“值”传递的"

要修改指向T的指针,可以将指向指向T的指针作为函数参数类型。


在计算机科学中,按引用传递意味着传递一个变量的地址。C++创建了一个与计算机科学中常规定义不同的定义。这并不意味着C++的定义是常规定义,而且问题本来就是关于C的。在C中,按引用传递意味着通过指针传递。C11 6.2.5 指针类型可以从函数类型或对象类型派生,称为引用类型。指针类型描述了一个对象,其值提供对引用类型实体的引用。从引用类型T派生的指针类型有时称为“指向T的指针”。 - Lundin
我不同意。在C语言中使用“按引用传递”这个词汇只会更加混淆初学者:在C语言中没有像C++中那样的引用。与其他语言相反,在C语言中没有两种(或更多)不同的方法来传递函数参数,你只能通过值传递;指针参数与任何其他参数一样传递。而且我认为§6.2.5中的C语言引用与按引用传递无关。 - ouah
顺便说一句,对于投反对票的人,我不会删除这个答案,因为我认为它不值得得到“-1”的评价 :) - ouah
正如你在上面引用的标准规范中所看到的,C语言确实存在一种称为“引用”的东西。它的定义可能与你想象的不同,并且确实令人困惑,但它确实存在。我没有给你点踩,但我认为整个关于引用的争论对原帖并没有好处。 - Lundin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接