C二分查找实现为什么传递地址而不是数组?

huangapple go评论51阅读模式
英文:

Why is the C binary search implementation passing an address instead of an array?

问题

我有这个'C'二分搜索程序:

#include <stdio.h>

typedef int element_t;

int less(a, b) {
  if (a < b)
    return 1;
  return 0;
}

element_t *binary_search(element_t x, element_t *a, int n) {
  if (n > 0) {
    int mid = n / 2;
    if (less(a[mid], x))
      return binary_search(x, a+mid+1, n-mid-1);
    if (less(x, a[mid]))
      return binary_search(x, a, mid);
    return a+mid;
    }
  return NULL;
}

int main(){

  int a[5] = {1,2,3,4,5};
  printf("%d %d", &a[2], binary_search(3, a, 5));
  return 0;
}

我不理解这部分 a+mid+1,它应该传递一个数组,但实际上传递的是一个地址,为什么会这样呢?a 数组 + 一个整数是关于地址的操作。

我在线上查阅了一些资料,但我无法理解发生了什么,因为在线上说 a+1 是索引为 1 的值的地址。

英文:

I have this C binary search program:

#include &lt;stdio.h&gt;

typedef int element_t;

int less(a, b) {
  if (a &lt; b)
    return 1;
  return 0;
}

element_t *binary_search(element_t x, element_t *a , int n) {
  if (n &gt; 0) {
    int mid = n / 2;
    if (less(a[mid], x))
      return binary_search(x, a+mid+1 , n-mid-1);
    if (less(x, a[mid]))
      return binary_search(x, a, mid);
    return a+mid;
    }
  return NULL;
}

int main(){

  int a[5] = {1,2,3,4,5};
  printf(&quot;%d %d&quot;, &amp;a[2], binary_search(3, a, 5));
  return 0;
}

I don't get this part a+mid+1, it is supposed to pass an array there, but an address is instead, how is that? and array a + an integer is about address.

I read online and I can't see what is going on, because online it says a+1 is the address of value at index 1.

答案1

得分: 2

为了回答你的问题,我们首先需要一些定义。

什么是数组?

数组是相同类型的变量集合,它们在内存中是连续的。
在C中,数组的名称(在本例中为a)是指向第一个元素位置的指针。

例如,在这段代码中:

#include &lt;stdio.h&gt;

int main(){

    int a[4]={0,1,2,3,4};
    int *ptr=&amp;a;
    int *ptr_a=a;

    return 0;
}

这两个指针都指向相同的内存位置。

什么是指针?

指针是一个存储内存位置的变量。指针具有特殊的算术操作,当你将1添加到指针时,你不是(总是)移动到下一个内存位置,而是添加指针类型的“权重”。

例如,如果你有一个char指针,你每次添加1字节,但是对于int指针,每次添加1会添加4字节(在64位系统上)。

指针和数组有什么关系?

由于数组名称在添加值时被转换为指针,你正在移动到下一个元素的内存位置。
使用[i]运算符等同于*(array+i)

你可以(这并不意味着你应该)不加区分地使用数组和指针。

这被称为“数组/指针二元性法则”。

英文:

To answer your question we first need a few definitions.

What is an array?

An array is a collection of variables of the same type which are contiguous to each other.
In C, the name of an array (in this case a) is a pointer to the memory position where the first element is located.

For example in this code:

#include &lt;stdio.h&gt;

int main(){

    int a[4]={0,1,2,3,4};
    int *ptr=&amp;a;
    int *ptr_a=a;

    return 0;
}

Both pointers point to the same memory location

What is a pointer?

A pointer is a variable which stores a memory position. Pointers have special arithmetic, when you add 1 to a pointer you are not (always) moving to the next memory position, you are adding the "weight" of the pointer type.

For example, if you have a char pointer you add by 1 byte at a time, but with int pointer you add 4 bytes(on 64-bit systems) each time you add 1.

What happens with pointers and arrays?

Since the array name is converted to a pointer when you add a value to it, you are moving to the memory position your next element is located.
And using the [i] operator is equivalent to *(array+i)

You can(this doesn't mean you should) use arrays and pointers indistinctively.

This is called "The Array/Pointer Duality Law"

答案2

得分: 2

除非它是sizeof_Alignof或一元&操作符的操作数,或者是用于声明中初始化字符数组的字符串字面值,类型为“N个元素的T数组”的表达式将被转换为类型为“指向T的指针”的表达式,并且表达式的值将是数组的第一个元素的地址。

当您调用一个带有数组参数的函数时,比如

int arr[10];
...
foo( arr );

编译器会将表达式 arr 替换为类似于

foo( &arr[0] );

函数接收到的是一个指针,而不是一个数组。

binary_search 函数中的 a 参数是一个指针,而不是一个数组,因此您可以对它进行指针算术运算。

在函数参数列表中,任何声明为 T a[N]T a[] 的参数都会被“调整”为 T *a;这三种方式都声明了 a 为指针。

这种行为有其原因。数组下标操作 a[i] 被定义为 *(a + i) - 给定某个起始地址 a,偏移 i 个元素并解引用结果。

然而,数组对象不存储地址;当您声明一个数组如下所示

int a[10];

在内存中所得到的是

   +---+
a: |   | a[0]
   +---+
   |   | a[1]
   +---+
    ...
   +---+
   |   | a[9]
   +---+

因此,这就是转换规则。不幸的是,这意味着在大多数情况下,数组都会失去它们的“数组性”。

英文:

Unless it is the operand of the sizeof, _Alignof, or unary &amp; operators, or is a string literal used to initialize a character array in a declaration, an expression of type "N-element array of T" will be converted, or "decay", to an expression of type "pointer to T" and the value of the expression will be the address of the first element of the array.

When you call a function with an array argument, such as

int arr[10];
...
foo( arr );

the compiler replaces the expression arr with something like

foo( &amp;arr[0] );

and what the function receives is a pointer, not an array.

The a parameter in the binary_search function is a pointer, not an array, so you can do pointer arithmetic on it.

In a function parameter list any parameters declared as T a[N] or T a[] are "adjusted" to T *a; all three declare a as a pointer.

There is a reason for this behavior. The array subscript operation a[i] is defined as *(a + i) - given some starting address a, offset i elements and dereference the result.

However, array objects do not store an address; when you declare an array as

int a[10];

what you get in memory is

   +---+
a: |   | a[0]
   +---+
   |   | a[1]
   +---+
    ...
   +---+
   |   | a[9]
   +---+

Hence the conversion rule. Unfortunately, this means arrays lose their "array-ness" in most circumstances.

huangapple
  • 本文由 发表于 2023年5月29日 10:36:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/76354384.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定