在我开始之前,我想告诉你我正在学习编程。
在C中将变量传递给函数和将数组传递给函数有什么区别?
当我们将变量传递给函数时,我们只是传递函数的值。但是,当我们传递数组时,我们以某种方式传递了一个指针,因为当我们对函数内部的数组进行一些更改时,实际的数组会被更改。
为了使我的问题更清楚,我附上了可以解释我所问问题的代码-
代码1:
//Passing variable to function
#include<stdio.h>
void swap(int x, int y);
int main(void)
{
//Nothing is happening to real values of variables
int x, y;
x = 1;
y = 2;
swap(x, y);
printf("%d = x \n %d = y", x, y);
}
void swap(int x, int y)
{
int temp;
temp = x;
x = y;
y = temp;
}
代码2:
//Here you can see the values of arrays are swapped.
#include<stdio.h>
void swap(int arr[]);
int main(void)
{
int idx, array[2];
for(idx = 0; idx < 2; idx++ )
{
scanf("%d", &array[idx]);
}
swap(array);
for(idx = 0; idx < 2; idx++, printf("\n"))
{
printf("%d", array[idx]);
}
}
void swap(int arr[])
{
int temp;
temp = arr[0];
arr[0] = arr[1];
arr[1] = temp;
}
也许我的问题仍然不清楚,但是我只想知道为什么main
函数中数组的值会发生变化,就像调用函数时我们只是传递该变量的函数值一样。
答案 0 :(得分:4)
在两种情况下,当您所说的变量传递给函数或数组传递给函数时,都会传递一个值。
但是在第一种情况下,传递了变量的值,而在第二种情况下,传递了指向数组第一个元素的指针的值。
表达式中使用的具有极少数例外的数组将转换为指向其第一个元素的指针。
根据C标准(6.3.2.1左值,数组和函数指示符)
3除非它是sizeof运算符的操作数或一元& 运算符,或者是用于初始化数组的字符串文字, 类型为“类型数组”的表达式将转换为 类型为“要输入的指针”的表达式指向初始 数组对象的元素,不是左值。如果数组对象 具有寄存器存储类,其行为是不确定的。
因此,拥有指向对象的指针,您可以更改指向的对象。
让我们假设您具有两个功能。
void f( int x )
{
x = 10;
}
and
void g( int *px )
{
*px = 10;
}
和他们的电话
int n = 0;
f( n );
g( &n );
您可以通过以下方式想象函数定义及其调用
int n = 0;
f( n );
g( &n );
// ...
void f( /* int x */ )
{
int x = n;
x = 10;
}
void g( /* int *px */ )
{
int *px = &n;
*px = 10;
}
这是两个函数都处理用作函数参数的表达式值的副本。但是在使用函数g
的情况下,该函数获取指向的对象n
的地址值,则可以使用指针(地址)来更改指向的对象n
。
在C语言中,通过指向对象的指针间接将对象传递给函数称为通过引用传递。
根据C标准
-指针类型可以从函数类型或对象派生 类型,称为引用类型。 指针类型描述了一个对象 其值提供对所引用实体的引用 类型。有时,从引用类型T派生的指针类型是 称为“ T的指针”。从一个指针类型的构造 引用的类型称为“指针类型派生”。指针类型 是完整的对象类型。
请注意这样的函数声明
void f( int a[], size_t n );
等效于以下声明
void f( int *a, size_t n );
两者都声明相同的一个函数。
例如,如果您有一个数组
#define N 10
//...
int a[N];
然后将其传递给类似的函数
f( a, N );
然后从C标准的第一引号开始遵循,数组指示符将转换为指向其第一个元素的指针。并且在函数中使用此指针可以更改数组的任何元素,因为数组的每个元素实际上都是通过引用传递的。使用指针算法,可以更改指向数组的任何元素。例如
void f( int *a, size_t n )
{
for ( int i = 0; i < n; i++ )
{
a[i] = i;
// that is the same as
// *( a + i ) = i;
}
}
答案 1 :(得分:2)
传递数组时,实际上是传递该数组的基地址,它是指向内存中第一个数组元素的指针。它本质上是通过引用进行的调用,因此在传递给交换函数时,无需显式使用引用或&
。 arr
衰减为&(arr[0])
。
另一方面,默认情况下,变量不是按值传递的,您需要显式使用&
来按引用传递变量,以将其值交换到它们的存储位置中,而不仅仅是特定于作用域交换功能。
答案 2 :(得分:2)
在C中将变量传递给函数和将数组传递给函数有什么区别?
不能将数组原样传递给函数。 C语法不允许这样做。当您提供数组的标识符作为参数时,它会衰减为指向数组第一个元素的指针-因此您可以通过引用数组将其传递给数组的第一个元素。
如果函数的相对参数为匹配的指针类型(此处为int *
或int a[]
,则允许)。
相反,当提供变量作为参数时,您按值传递变量。意味着您不访问函数本身中作为参数提供的变量。而是将值复制到函数的局部变量中。
如果要更改自己传递的变量的值,则需要使用&
和号运算符来收集变量本身的地址。仅当相对参数具有如上所述的匹配指针类型时,才允许这样做。
因此,在第一个示例中,您没有交换x
中的y
和main()
的值。您只需在x
内更改y
和swap()
,这几乎没有用。
如果要在主体上交换x
和y
,则需要将swap()
定义为:
void swap(int* x, int* y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}
并像这样呼叫swap()
:
swap(&x, &y);
我建议您进一步了解指针。
答案 3 :(得分:1)
您没有将数组作为副本传递。它只是指向第一个元素在内存中的地址的指针。
在将数组作为参数传递时,此
$cad = "aAAAAB+LCAAAAAAABAAtyjEKgDAMQNGrhMwquPYGHVx0FIfYRqloAm11Ee+uFLfP591o5WLJFIMmNONUYZdW69HUbckhRzTY88KRxQUCAp03zgqiwCnTvLMLnsDpoRDkO4V5hlN+2uDzAmqxWoNoAAAA";
$cad_base64_decoded = base64_decode($cad);
$gz = gzdecode(substr($cad_base64_decoded, 4));
echo $gz;
// result:
// {"Inventarios":[],"MsgId":-1,"MsgStr":"Referencia a objeto no establecida como instancia de un objeto."}
与...完全相同
void arraytest(int a[])
因此您正在修改main中的值。但是,在C函数中,参数始终按值传递。对于数组(变量),作为函数参数传递时,它会衰减到指向数组第一个元素的指针。然后,照常按指针传递值。
答案 4 :(得分:1)
数组是一个特殊变量。将常规变量作为参数传递给函数时,其值将被复制到与该函数有关的局部变量。
将数组作为参数传递给函数时,该数组的第一个元素的地址将复制到与该函数有关的局部变量中。
基本上,这是传递常规变量和将数组传递给函数之间的区别。
尽管您的看法有一个问题。如果要修改要传递给函数的常规变量,则需要将其地址传递给函数,因此函数应采用指针类型。因此,即使它们等同于函数参数,也只需使用指针符号,即int *p
而不是int p[]
。
您的代码应如下所示:
#include<stdio.h>
void swap(int *x, int *y);
int main(void)
{
int x, y;
x = 1;
y = 2;
swap(&x, &y);
printf("%d = x \n %d = y", x, y);
}
void swap(int *x, int *y)
{
int temp;
temp = *x;
*x = *y;
*y = temp;
}