Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 数组是按值传递还是按引用传递?_C_Arrays_String_Pointers - Fatal编程技术网

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";