通过使用&;将数组重新分配给其中一个元素来减少数组;c中的运算符

通过使用&;将数组重新分配给其中一个元素来减少数组;c中的运算符,c,arrays,pointers,C,Arrays,Pointers,我为二进制搜索编写了一个简单的递归函数,它包含三个参数:整数数组、数组长度和要查找的值。其思想是,在每次递归调用时,它要么将长度减半,并将数组[0]保持在适当的位置,要么将起始索引移到中间(在我的示例中,从底部算起的第三行)。直到找到值或长度为0为止 然后我看到了这个讨论: 这里说数组名是常量,不能在C中重新赋值。所以我的问题是为什么这段代码有效 int rsearch( int needle, int haystack[], int size ) { if (size == 0) {

我为二进制搜索编写了一个简单的递归函数,它包含三个参数:整数数组、数组长度和要查找的值。其思想是,在每次递归调用时,它要么将长度减半,并将数组[0]保持在适当的位置,要么将起始索引移到中间(在我的示例中,从底部算起的第三行)。直到找到值或长度为0为止

然后我看到了这个讨论:

这里说数组名是常量,不能在C中重新赋值。所以我的问题是为什么这段代码有效

int rsearch( int needle, int haystack[], int size ) {

if (size == 0) {
    printf("%i not found\n", needle);
    return 0;
}

int mid = size / 2;

if (haystack[mid] == needle) {
    printf( "found %i in the array\n", needle );
    return 1;

} else if (haystack[mid] > needle) {
    return rsearch( needle, haystack, size / 2 );

} else {
    haystack = &haystack[mid + 1];
    return rsearch( needle, haystack, (size - 1) / 2 );
}
我只是在学习,我对指针的知识非常有限。这里没有实际应用。只是好奇

附言。
另一个问题是,当分配给原始数组的内存以这种方式减少时,会发生什么情况?它是再次可用还是内存泄漏?

作为函数参数,如下所示:

int haystack[]
相当于:

int *haystack
这主要是因为数组在传递给函数时衰减为指向第一个元素的指针


因此,您拥有的不是数组,而是指针。与数组不同,指针是一个可修改的左值,因此允许将其赋值。

数组用作函数参数时,实际上是指向数组的指针,而不是数组作为值。因此,以下函数签名是等效的:
无效测试(int-xptr[10])
无效测试(int-xptr[])
,以及
无效测试(int*xptr)

但是,在定义数组时,只能初始化它的值,但以后不能指定任何其他值

当你把一个数组传递给一个函数时,比如说,
int x[10]
,只需使用
x
作为参数,就像在
test(x)
中一样,然后数组
x
自动衰减为指向
x
的第一个元素的指针

请参见以下显示差异的代码:

#include <stdio.h>

void test(int xptr[10]) {

    printf("value of xptr[0]: %d\n", xptr[0]); // -> 0

    xptr = &xptr[2];  // OK; xptr will point to element 2

    printf("value of xptr[0]: %d\n", xptr[0]); // -> 2
}

int main(){

    int x[10] = { 0,1,2,3,4,5,6,7,8,9 };

    // x = &x[2];  // Error: Array type 'int [10]' is not assignable

    // but:
    test(x);  // OK; and is eqivalent to...
    test (&x[0]); // OK;

    return 0; 
}
#包括
无效测试(int xptr[10]){
printf(“xptr[0]的值:%d\n”,xptr[0]);//->0
xptr=&xptr[2];//确定;xptr将指向元素2
printf(“xptr[0]的值:%d\n”,xptr[0]);//->2
}
int main(){
int x[10]={0,1,2,3,4,5,6,7,8,9};
//x=&x[2];//错误:数组类型“int[10]”不可赋值
//但是:
测试(x);//好;与…相等。。。
测试(&x[0]);//确定;
返回0;
}

根据C标准(6.7.6.3功能声明器(包括原型))

7应调整“类型数组”的参数声明 到“类型的限定指针”

和(6.3.2.1左值、数组和函数指示符)

3除非它是sizeof运算符或一元数的操作数& 运算符,或是用于初始化数组的字符串文字 类型为“”的数组“”的表达式转换为 类型为“指向类型的指针”且指向初始值的表达式 数组对象的元素,并且不是左值。如果数组对象 已注册存储类,行为未定义

因此在这个函数声明中

int rsearch( int needle, int haystack[], int size );
参数
int haystack[]
调整为
int*haystack
。所以这些函数声明

int rsearch( int needle, int haystack[100], int size );
int rsearch( int needle, int haystack[10], int size );
int rsearch( int needle, int haystack[], int size );
int rsearch( int needle, int *haystack, int size );
声明同一个函数。您可以在程序中包含所有这些声明,因为函数声明可能会出现多次。但是,该函数只能定义一次(如果它不是内联函数)

因此,作为参数传递给函数的数组被隐式转换为指向其第一个元素的指针

考虑到最好像这样声明函数

int rsearch( int needle, const int *haystack, int size );
                         ^^^^^
在这种情况下,该函数也可以用于常量数组

这里说数组名是常量,不能为空 重新分配给C

可以正确地说,数组不是可修改的左值

来自C标准(6.5.16赋值运算符)

2赋值运算符的左侧应为可修改的左值 操作数

和(6.3.2.1左值、数组和函数指示符)

  • …可修改左值是没有数组类型的左值,

  • 当数组被传递给函数时,它将退化为指针,就函数而言不再是数组。这是微妙的,你可能需要进一步阅读来理解这一点。函数参数也是通过C中的值传递的。因此,函数中的haystack只是指向原始数组开头的指针,而不是数组“name”本身。@kaylum非常感谢。我想我明白了。谢谢。这是非常详尽的。