对此问题感到困惑。 C的新手,如下例所示:
#include <stdlib.h>
#include <stdio.h>
void pass_char_ref(unsigned char*);
int main()
{
unsigned char bar[6];
pass_char_ref(&bar);
printf("str: %s", bar);
return 0;
}
void pass_char_ref(unsigned char *foo)
{
foo = "hello";
}
据我所知,bar是一个无符号字符数组,其元素大小为6,静态存储。我只想通过引用pass_char_ref()传递bar并在该函数中设置字符数组,然后将其打印回main()。
答案 0 :(得分:7)
您需要将字符串复制到数组中:
void pass_char_ref(unsigned char *foo)
{
strcpy( foo, "hello" );
}
然后当你调用该函数时,只需使用数组的名称:
pass_char_ref( bar );
此外,该阵列不在“静态存储”中;它是一个自动对象,在堆栈上创建,具有包含函数调用的生命周期。
答案 1 :(得分:4)
两件事:
您无需通过&bar
;只需通过bar
。
当你传递这样的数组时,它的第一个(第0个)元素的地址作为指针传递给函数。所以,请像这样呼叫pass_char_ref
:
pass_char_ref(bar);
当您像这样调用pass_char_ref
时,数组名称“衰减”为指向数组第一个元素的指针。这个in this tutorial还有更多内容,但短篇小说是你可以在表达式中使用数组的名称作为&array_name[0]
的同义词。
指针按值传递。你有:
void pass_char_ref(unsigned char *foo)
{
foo = "hello";
}
在其他一些语言中,参数通过引用传递,因此形式参数基本上是参数的别名。在这种语言中,您可以将"hello"
分配给foo
,它会更改bar
的内容。
由于这是C,foo
是传入指针的副本。因此,foo = "hello";
实际上不会影响bar
;它将本地值(foo
)设置为指向const
字符串"hello"
。
要在C中通过引用传递,你必须按值传递指针,然后修改它们指向的内容。 e.g:
#include <string.h>
void pass_char_ref(unsigned char *foo)
{
strcpy(foo, "hello");
}
这将将<{1}}字符串复制到"hello"
指向的内存位置。由于您传递了foo
的地址,因此strcpy将写入bar
。
有关bar
的详情,请查看its man page。
答案 2 :(得分:1)
在C中,使用与指针类似的机制来访问数组,但它们在定义的工作方式上有很大的不同 - 数组定义实际上会导致分配数组的空间。指针定义将导致分配足够的存储空间以引用(或“指向”)内存的某些其他部分。
unsigned char bar[6];
为6个无符号字符创建存储空间。 C数组语义表示,当您将数组传递给另一个函数时,不是在堆栈上创建数组的副本,而是将指向数组中第一个元素的指针作为函数的参数。这意味着
void pass_char_ref(unsigned char *foo)
不是将数组作为参数,而是指向数组的指针。更新指针值(如在foo = "hello";
中,用编译后的字符串"hello"
的地址覆盖指针的值)不影响原始数组。您可以通过取消引用指针来修改原始数组,并覆盖它指向的内存位置。这是strcpy
例程在内部执行的操作,这就是人们建议您使用
void pass_char_ref(unsigned char *foo)
{
strcpy(foo, "hello");
}
代替。你也可以说(为了说明):
void pass_char_ref(unsigned char *foo)
{
foo[0] = 'h';
foo[1] = 'e';
foo[2] = 'l';
foo[3] = 'l';
foo[4] = 'o';
foo[5] = 0;
}
它也会表现正常。 (这类似于strcpy在内部的表现。)
HTH
答案 3 :(得分:1)
请参阅here对指针的解释,并通过另一张SO海报的问题参考。此外,here是对字符指针和字符数组之间差异的另一个彻底解释。
您的代码不正确,因为在ANSI C标准中,您无法将数组传递给函数并通过引用传递它 - 除char
之外的其他数据类型都能够执行此操作。此外,代码不正确,
void pass_char_ref(unsigned char *foo) { foo = "hello"; }
您不能以这种方式将指针分配给字符串文字,因为指针使用左值和右值赋值语义(分别为左值和右值)。字符串文字不是 rvalue 因此它将失败。顺便说一句,在我给出的第二个链接中解释了指针和数组之间的差异,我提到了一本很好的书,它将解释很多关于第二个链接的指针。
这段代码可能对你想要实现的目标更有意义
void pass_char_ref(unsigned char *foo) { strcpy(foo, "hello"); }
在main()
中,就像这样
int main() { unsigned char bar[6]; pass_char_ref(bar); printf("str: %s", bar); return 0; }
不要忘记在代码#include <string.h>
的顶部添加另一行。
希望这有帮助, 最好的祝福, 汤姆。
答案 4 :(得分:0)
由于bar []是一个数组,当你编写bar时,你正在使用指向该数组的第一个元素的指针。所以,而不是:
pass_char_ref(&bar);
你应该写:
pass_char_ref(bar);
答案 5 :(得分:0)
通常的间隔时间再次 -
当大多数上下文中出现数组类型的表达式时,其类型将从“N元素数组T”隐式转换为“指向T”,其值设置为指向数组的第一个元素。此规则的例外情况是,数组表达式是sizeof
或&
运算符的操作数,或者数组是一个字符串文件,用作声明中的初始化程序。
那么代码上下文中的含义是什么呢?
表达式bar
的类型是“6元素无符号字符数组”(unsigned char [6]
);在大多数情况下,类型将被隐式转换为“指向unsigned char”(unsigned char *
)的指针。但是,当您致电pass_char_ref
时,请将其称为
pass_char_ref(&bar);
&
运算符阻止隐式转换发生,表达式&bar
的类型是“指向无符号字符的6元素数组的指针”(unsigned char (*)[6]
),显然与原型不匹配
void pass_char_ref(unsigned char *foo) {...}
在这种特殊情况下,正确答案是抛弃函数调用中的&
并将其称为
pass_char_ref(bar);
现在是第二个问题。在C中,您无法使用=
运算符以C ++和其他语言的方式分配字符串值。在C中,字符串是char的数组,其终止为0,并且您不能使用=
将一个数组的内容分配给另一个数组。您必须使用像strcpy
这样的库函数,它需要char *
类型的参数:
void pass_char_ref(unsigned char *foo)
{
strcpy((char *)foo, "hello");
}
这是一个数组表达式表,它们对应的类型以及任何隐式转换,假设一个类型为T(T a[N]
)的一维数组:
Expression Type Implicitly converted to
---------- ---- -----------------------
a T [N] T *
&a T (*)[N]
a[0] T
&a[0] T *
请注意,表达式a
,&a
和&a[0]
都提供相同的值(数组中第一个元素的地址),但类型都不同。
答案 6 :(得分:-1)
不再允许在数组上使用运算符(&amp;)的地址。我同意做&amp; bar而不是bar更有意义,但由于数组总是通过引用传递,因此使用&amp;这是多余的,随着C ++的出现,标准委员会将其定为非法。
所以只要抵制放置&amp;的冲动在酒吧之前,你会没事的。
编辑:与罗杰谈话后,我撤回非法一词。这是合法的,只是没用。