C 数组是按值传递还是按引用传递?
我确信这一点C 数组是按值传递还是按引用传递?,c,arrays,string,pointers,C,Arrays,String,Pointers,我确信这一点 function(int *a); function(int a[]); 在C语言中,函数(inta[])将被转换为函数(int*a) 这两个不一样,第一个是指针,第二个是数组。调用函数(b)时会发生什么情况?(函数(int*a)) 我知道b在堆栈上,那么如何传递给该函数呢 第二,字符串: char *c1 = "string"; char c2 [] = "string"; 在这种情况下,我不知道c1在哪里,我假设c2在堆栈上。 假设该函数现在是:function(char*
function(int *a); function(int a[]);
在C语言中,函数(inta[])将被转换为函数(int*a)
这两个不一样,第一个是指针,第二个是数组。调用函数(b)时会发生什么情况?(函数(int*a))
我知道b在堆栈上,那么如何传递给该函数呢
第二,字符串:
char *c1 = "string";
char c2 [] = "string";
在这种情况下,我不知道c1在哪里,我假设c2在堆栈上。
假设该函数现在是:function(char*c),它与function(char c[])相同,当我调用function(c1)和function(c2)时会发生什么情况,字符串将通过引用或值传递?编辑:下面的答案是错误的。
“数组总是通过引用传递的。”这是错误的。有关
为什么
部分,请参阅。
然而,我在下面保留了这个答案,用于结构技巧中的封装,将数组的副本传递给函数
数组总是通过引用(指针)传递 如果要使用value传递它们,请将它们封装在
结构中。这将导致对原始阵列的副本进行操作。示例如下所示:
foo的第一个参数是struct object,它保存数组的副本。第二个参数是数组引用
#include <stdio.h>
struct a{
int i[2]; // An array encapsulated in struct.
};
void foo(struct a b, int j[]){
b.i[0]=30;
j[1]=30;
}
int main(){
struct a c;
c.i[0]=10;
c.i[1]=20;
printf("Before %d %d\n",c.i[0], c.i[1]);
foo(c, c.i);
printf("After %d %d \n",c.i[0], c.i[1]);
return 0;
}
$ ./a.out
Before 10 20
After 10 30
#包括
结构a{
int i[2];//封装在struct中的数组。
};
void foo(结构a b,int j[]{
b、 i[0]=30;
j[1]=30;
}
int main(){
结构a-c;
c、 i[0]=10;
c、 i[1]=20;
printf(“在%d%d\n之前”,c.i[0],c.i[1]);
foo(c,c.i);
printf(“在%d%d\n之后,c.i[0],c.i[1]);
返回0;
}
美元/年
10点20分之前
10点30分以后
来自K&R2
When an array name is passed to a function, what is passed is the
location of the initial element. Within the called function, this
argument is a local variable, and so an array name parameter is a
pointer, that is, a variable containing an address.
参数声明char c2[]
只是char*c2
的语法糖
C中的所有内容都作为值传递。如需进一步解释,请使用此
此外,Eli Bendersky对这一点也有很好的讨论。这里有一个关键点需要说明,一切都是按值传递的。例如,这将把a
的副本传递给foo()
(恰好是指向某个内存的指针):
这就是为什么如果在foo()
中执行类似操作,它实际上不会更改main()
中的指针a
,而是更改本地副本:
换句话说,您可以使用foo()
的a
本地副本来更改由“a”指向的内存,但不能更改a
在main()
中指向的内容
现在,要“通过引用”传递某些内容,您需要传递一个指向函数指针的指针副本(类似于a->b->memory):
因此,当您在foo()
中为其赋值以更改main()
中的指针时:
现在要回答一些其他问题,当您使用数组名称时,它将转换为指向数组第一个元素的指针:
int *a = malloc(20);
int b[] = {1,2,3,4,5};
foo(a);
foo(b);
最后两个函数调用是等效的,它们都传递一个指向某个内存的第一个元素的指针,不同之处在于a
的内存是在堆上分配的,而b
的内存是在堆栈上分配的
最后,字符串与以下内容类似,因为相同的原则适用,但是第一个字符串是常量字符串文字,应定义为const
,您不应尝试在任何地方修改它,但可以更改第二个:
const char *c1 = "string";
char c2 [] = "string";
数组是通过引用传递的,为什么?因为您是按值传递指针地址的,所以更改该指针将在指针内存中更改,而不是指针地址本身,因此更改指针不会替换函数中的原始指针,因此,当您在该函数中键入a=另一个_指针时,它不会在使用该函数后丢失传递的数组
inta[]相当于inta,调用函数foo(inta)时,它将获得指针地址
现在,如果您想自行更改指针,您可以通过引用foo(int*&a)传递指针地址,因此现在更改指针地址a=另一个\u指针将更改指针地址如果您认为它是按值调用的,请尝试运行以下操作:
void bubbleSort(int a[],int n){ //or int *a
printf("\nBUBBLE SORT");
int i,j;
for(i=n-1;i>0;i--)
for(j=0;j<i;j++)
if(a[j]>a[j+1])
swap(&a[j],&a[j+1]);
displayArray(a,n);
}
main(){
int n=5,a[n],i,j;
initArray(a,n);
displayArray(a,n);
bubbleSort(&a,n);
displayArray(a,n);
}
完全一样!
在这两种情况下,c都指向字符串中的第一个元素。另外,第一个字符串不是,我的意思是不是常数。试着改变它。它将。如果您执行char c2[]=“string”
它将不在只读内存中。string将处于readonly
状态,它的一个副本将被复制到堆栈上的c2
数组。这是实现它的一种可能方法,但您正在讨论实现细节。最终结果是不在只读内存中的内容。@DietrichEpp从技术上讲,文本“字符串”将始终放在只读内存中,但编译器可以自由地优化其分配,只为c2分配空间。也就是说,如果编译器是为纯基于RAM的系统(如PC)编写的。否则,什么也做不到,字符串文本必须在ROM中分配。@Lundin:从技术上讲,根本不需要只读内存(我可以想到一些C实现没有它),我们唯一可以确定的是,c2
不在只读存储器中。虽然这是正确的,但对于初学者来说,这并不是真正的教学方法。最好说明func(int*x)
是通过值,而func(int*x)
是通过引用。因为它是通过val还是通过ref,实际上取决于函数的意图。否则你可以说你的例子foo(int**a)
没有通过引用传递任何东西,它只是通过值传递指向指针的指针。@Lundin我想,IMHO,所有初学者都会尝试在函数中指定一个指针,并期望它在其他地方更改它,这就是说某些东西是通过引用传递的
int *a = malloc(20);
foo(&a);
foo(int **a)
{
*a = NULL; /*changes the pointer in main */
}
int *a = malloc(20);
int b[] = {1,2,3,4,5};
foo(a);
foo(b);
const char *c1 = "string";
char c2 [] = "string";
int *a = malloc(20);
===========
|a|----------------> | | | | | |
===========
a is a pointer 20 bytes on heap each of 4 bytes
to int on stack
int b[] = {1,2,3,4,5};
=================================
| 1 | 2 | 3 | 4 | 5 |
=================================
b[0] b[1] b[2] b[3] b[4]
Full array is on stack
char *c1 = "string";
char c2 [] = "string";
In case of "string" it's string literal and allocated on readonly memory.
In first case , |c1| ----> |s|t|r|i|n|g|\0|
In second case , ============================================
| s | t | r | i | n | g | \0 |
============================================
c2[0] c2[1] c2[2] c2[3] c2[4] c2[5] c2[6]
The full char array is on stack.
void bubbleSort(int a[],int n){ //or int *a
printf("\nBUBBLE SORT");
int i,j;
for(i=n-1;i>0;i--)
for(j=0;j<i;j++)
if(a[j]>a[j+1])
swap(&a[j],&a[j+1]);
displayArray(a,n);
}
main(){
int n=5,a[n],i,j;
initArray(a,n);
displayArray(a,n);
bubbleSort(&a,n);
displayArray(a,n);
}
char *c="blah-blah"; and,
char c[]="blah-blah";