为什么指针黑客在C中查找数组的大小,在被调用函数中使用时给出不同的值

为什么指针黑客在C中查找数组的大小,在被调用函数中使用时给出不同的值,c,arrays,function,C,Arrays,Function,下面是说明问题的代码: #include <stdio.h> void func(int arr[]); int main() { int arr[10]; int n = *(&arr + 1) - arr; printf("%d\n", n); func(arr); return 0; } void func(int arr[]) { int n = *(&arr + 1) - arr; printf(

下面是说明问题的代码:

#include <stdio.h>

void func(int arr[]);

int main() {
    int arr[10];
    int n = *(&arr + 1) - arr;
    printf("%d\n", n);
    func(arr);
    return 0;
}

void func(int arr[]) {
    int n = *(&arr + 1) - arr;
    printf("%d\n", n);
}

在函数中声明数组参数时,它根本不是数组,而是指针

宣言

void funct(int arr[]);
实际上等于

void funct(int *arr);

这就是你看到的结果之间的差异。在
main
函数中
&arr
是指向数组的指针,但在
func
中表达式
&arr
是指向指针变量的指针。这两个指针非常不同。

尽管其定义使用了语法
void func(int arr[])
,但function
func
接收指向数组第一个元素的指针。定义更清晰,因为
void func(int*arr)

如果
arr
定义为数组,则表达式
*(&arr+1)-arr
仅在编译时计算数组的元素数。如果
arr
是一个指针,它将取消指针后面的内存引用并减去指针值,这是没有意义的,并且在大多数情况下具有未定义的行为

用于获取数组元素数的更常见(且可读性更强)的表达式是

n = sizeof(arr) / sizeof(*arr);

如果
arr
是一个数组,则将其字节大小除以以字节为单位的元素大小,得到元素数。表达式在编译时求值,没有运行时开销。如果
arr
是一个指针,则将其大小除以它所指向的类型的大小是已定义的,但没有用,就像表达式一样。

每当数组作为参数传递给函数时,它们都会衰减为函数参数中的指针

:

由于数组会立即衰减为指针,因此数组永远不会消失 实际传递给函数。你可以假装一个函数 接收数组作为参数,并通过声明 作为数组的对应参数:

void f(char a[]){…}


编译器将数组
arr
的名称衰减到指向数组第一个元素的指针中。因此,取消对指针的引用会产生存储在数组第一个位置的值。

int n=*(&arr+1)-arr。你确定吗?@SouravGhosh No这是正确的(因为它很可能会工作,即使它在技术上是无效的)
&arr+1
是一个指向数组的指针,取消对它的引用(即
*(&arr+1)
)就会得到一个数组,然后数组会衰减为指向它的第一个元素的指针(它将指向
arr
末尾之外的一个元素,即实际上是指向
arr[10]
)的指针)。JensGustedt:这个问题不是完全重复的,它使用不同的表达式来计算数组大小。
n = sizeof(arr) / sizeof(*arr);