以下是 C Programming Just the FAQs 一书的摘录。这不是错误的,因为Arrays永远不能通过引用传递吗?
VIII.6:如何通过值将数组传递给函数?
答案:通过声明,可以按值将数组传递给函数 被调用的函数是数组名 方括号(
[
和]
) 附在最后。打电话的时候 功能,只需传递地址 数组(即数组的名称) 到被调用的函数。例如, 以下程序传递数组x[]
到名为的函数byval_func()
按值:
int[]
参数告诉我们 编译器byval_func()
函数将采用一个参数 - 一个 整数数组。当。。。的时候 你调用byval_func()
函数 将数组的地址传递给byval_func()
:byval_func(x);
因为数组正在传递 value,数组的精确副本 制作并放置在堆栈上。该 调用函数然后接收这个 数组的副本,可以打印出来。 因为数组传递给了
byval_func()
是该副本 原始数组,修改数组 在byval_func()
函数中有 对原始阵列没有影响。
答案 0 :(得分:59)
因为数组是按值传递的,所以会生成数组的精确副本并将其放在堆栈上。
这是不正确的:数组本身没有被复制,只有指向其地址的指针的副本被传递给被调用者(放在堆栈上)。 (无论您是将参数声明为int[]
还是int*
,它都是decays into a pointer。)这允许您从被调用函数中修改数组的内容。因此,这个
因为传递给byval_func()的数组是原始数组的副本,所以修改byval_func()函数中的数组对原始数组没有影响。
是完全错误的(感谢@Jonathan Leffler对他的评论)。但是,在函数内重新分配指针不会更改指向函数外部原始数组的指针。
答案 1 :(得分:51)
烧掉那本书。如果你想要一个不是由初学者程序员编写的真正的C FAQ,请使用这个:http://c-faq.com/aryptr/index.html。
语法方面,严格来说,不能按C中的值传递数组。
void func (int* x); /* this is a pointer */
void func (int x[]); /* this is a pointer */
void func (int x[10]); /* this is a pointer */
然而,对于记录,C中有一个脏技巧,它允许你在C中按值传递一个数组。不要在家里尝试这个!因为尽管有这个技巧,仍然没有理由按值传递数组。
typedef struct
{
int my_array[10];
} Array_by_val;
void func (Array_by_val x);
答案 2 :(得分:1)
在C和C ++中,不可能通过值将完整的内存块作为参数传递给函数,但我们可以传递其地址。在实践中,这具有几乎相同的效果,并且是更快和更有效的操作。
为安全起见,您可以传递数组大小或在指针之前放置const限定符,以确保被调用者不会更改它。
答案 3 :(得分:1)
这不是错误的吗,因为数组永远不能通过值传递?
完全正确。您不能在C中按值传递数组。
我看了一下书中引用的部分,很快就能发现这种混乱或错误的根源。
当将*i
用作函数的参数时,作者并不知道i[]
等效于i
。发明后一种形式是为了清楚地说明代码的读者,byval_func()
指向一个数组,这个问题很好地说明了这种混乱的根源。
我认为很有趣的是,该书特定部分的作者或至少一个其他部分的作者(因为该书总共有 5 位作者)或其中一个 7 校对人员至少没有提到以下句子:
“ 调用
byval_func()
函数时,您将数组的地址传递给#include <stdio.h> struct a_s { int a[20]; }; void foo (struct a_s a) { size_t length = sizeof a.a / sizeof *a.a; for(size_t i = 0; i < length; i++) { printf("%d\n",a.a[i]); } } int main() { struct a_s array; size_t length = sizeof array.a / sizeof *array.a; for(size_t i = 0; i < length; i++) { array.a[i] = 15; } foo(array); }
:”
至少,他们应该注意到存在冲突。 由于您传递的是地址,因此它只是一个地址。没有什么神奇的事情可以将地址变成一个全新的数组。
但是回到问题本身:
由于您似乎已经了解自己,因此无法按C中的值传递数组。但是您可以做三件事(可能还有更多,但这是我的正式要求),根据情况的不同,可以选择其他方法,所以让我们开始吧。
#include <stdio.h>
void foo (int *array, size_t length)
{
int b[length];
for(size_t i = 0; i < length; i++)
{
b[i] = array[i];
printf("%d\n",b[i]);
}
}
int main()
{
int a[10] = {0,1,2,3,4,5,6,7,8,9};
foo(a,(sizeof a / sizeof *a));
}
#include <stdio.h>
int a[10];
size_t length = sizeof a / sizeof *a;
void foo (void)
{
for(size_t i = 0; i < length; i++)
{
printf("%d\n",a[i]);
}
}
int main()
{
for(size_t i = 0; i < length; i++)
{
a[i] = 25;
}
foo();
}
CREATE trigger [dbo].[insercionVentasConcluidadas]
on [dbo].[pedido]
after update
as
declare @fechaactual date
declare @estado varchar
begin
if UPDATE(estado)
begin
select @estado = estado from inserted;
set @fechaactual = GETDATE();
if (@estado = 'cerrado')
print N'RAS'
begin
insert into ventaConcluida(numeroPedido, nombreCliente, nombreProveedor, fechaCreacion, fechaCierre, diasTranscurridos, MontoPedido)
select d.idPedido, d.nombreCliente, d.nombreProveedor, d.fechaPedido, @fechaactual, dbo.calculoDias(d.fechaPedido, @fechaactual),
d.montoPedido
from inserted i
inner join deleted d
on i.idPedido = d.idPedido
end
end
end
答案 4 :(得分:0)
Yuo可以通过将数组包装到struct中来解决此问题
#include <stdint.h>
#include <stdio.h>
struct wrap
{
int x[1000];
};
struct wrap foo(struct wrap x)
{
struct wrap y;
for(int index = 0; index < 1000; index ++)
y.x[index] = x.x[index] * x.x[index];
return y;
}
int main ()
{
struct wrap y;
for(int index = 0; index < 1000; index ++)
y.x[index] = rand();
y = foo(y);
for(int index = 0; index < 1000; index ++)
{
printf("%d %s", y.x[index], !(index % 30) ? "\n" : "");
}
}
答案 5 :(得分:-14)
#include<stdio.h>
void fun(int a[],int n);
int main()
{
int a[5]={1,2,3,4,5};
fun(a,5);
}
void fun(int a[],int n)
{
int i;
for(i=0;i<=n-1;i++)
printf("value=%d\n",a[i]);
}
通过这种方法,我们可以按值传递数组,但实际上数组正在通过其基本地址进行访问,该地址实际上是在堆栈中复制的。