关于C#:为什么数组参数的大小与main中的大小不同?

Why isn't the size of an array parameter the same as within main?

为什么作为参数发送的数组的大小与main中的相同?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>

void PrintSize(int p_someArray[10]);

int main () {
    int myArray[10];
    printf("%d
"
, sizeof(myArray)); /* As expected, 40 */
    PrintSize(myArray);/* Prints 4, not 40 */
}

void PrintSize(int p_someArray[10]){
    printf("%d
"
, sizeof(p_someArray));
}

将数组类型传递给函数时,会隐式转换为指针类型。

所以,

1
2
3
4
void PrintSize(int p_someArray[10]) {
    printf("%zu
"
, sizeof(p_someArray));
}

1
2
3
4
void PrintSize(int *p_someArray) {
    printf("%zu
"
, sizeof(p_someArray));
}

是等价的。所以你得到的是sizeof(int*)的价值


它是一个指针,这就是为什么它是一个常见的实现,将数组的大小作为第二个参数传递给函数


正如其他人所说,当用作函数参数时,数组会衰减到指向第一个元素的指针。还值得注意的是,sizeof不评估表达式,并且在与表达式一起使用时不需要括号,因此您的参数实际上根本不被使用,因此您也可以使用类型而不是值来编写sizeof。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <stdio.h>

void PrintSize1 ( int someArray[][10] );
void PrintSize2 ( int someArray[10] );

int main ()
{
    int myArray[10];
    printf ("%d
"
, sizeof myArray ); /* as expected 40 */
    printf ("%d
"
, sizeof ( int[10] ) ); /* requires parens */
    PrintSize1 ( 0 ); /* prints 40, does not evaluate 0[0] */
    PrintSize2 ( 0 ); /* prints 40, someArray unused */
}

void PrintSize1 ( int someArray[][10] )
{
    printf ("%d
"
, sizeof someArray[0] );
}

void PrintSize2 ( int someArray[10] )
{
    printf ("%d
"
, sizeof ( int[10] ) );
}

因此,您需要将数组的长度作为第二个参数传递。当您编写代码时,您既要声明一个常量大小的数组,然后将该数组传递给函数,那么让数组长度常量显示在代码中的几个位置是很痛苦的...

K&R救援:

1
#define N_ELEMENTS(array) (sizeof(array)/sizeof((array)[0]))

所以现在你可以这样做:

1
2
3
int a[10];
...
myfunction(a, N_ELEMENTS(a));


你发现的行为实际上是C语言中的一个大问题。每当您声明一个带有数组参数的函数时,编译器都会忽略您并将参数更改为指针。所以这些声明都表现得像第一个:

1
2
3
4
5
void func(int *a)
void func(int a[])
void func(int a
typedef int array_plz[5];
void func(array_plz a)

a将是所有四种情况下指向int的指针。如果将数组传递给func,它将立即衰减为指向其第一个元素的指针。 (在64位系统上,64位指针的大小是32位int的两倍,因此您的sizeof比率返回2.)

此规则的唯一目的是保持与不支持将聚合值作为函数参数传递的历史编译器的向后兼容性。

这并不意味着将数组传递给函数是不可能的。你可以通过将数组嵌入到结构中来解决这个问题(这基本上是C ++ 11的std :: array的目的):

1
2
3
4
5
6
7
8
struct array_rly {
int a[5];
};
void func(struct array_rly a)
{
printf("%zd
"
, sizeof(a.a)/sizeof(a.a[0]));  /* prints 5 */
}

或者通过传递指向数组的指针:

1
2
3
4
5
void func(const int (*a)[5])
{
printf("%zd
"
, sizeof(*a)/sizeof((*a)[0]));  /* prints 5 */
}

如果数组大小不是编译时常量,则可以将指针到数组技术与C99可变长度数组一起使用:

1
2
3
4
5
void func(int n, const int (*a)[n])
{
printf("%zd
"
, sizeof(*a)/sizeof((*a)[0]));  /* prints n */
}

因为数组在作为参数传递时会衰减为指针。这就是C的工作原理,尽管你可以通过引用传递C ++中的"数组"并克服这个问题。请注意,您可以将不同大小的数组传递给此函数:

1
2
 // 10 is superfluous here! You can pass an array of different size!
void PrintSize(int p_someArray[10]);


在c ++中,您可以为此目的通过引用传递数组:

1
2
3
4
5
void foo(int (&array)[10])
{
    std::cout << sizeof(array) <<"
"
;
}


您无法将数组传递给函数。

如果你真的想要打印大小,可以将指针传递给数组,但它根本不是通用的,因为你需要定义函数的数组大小。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>

void PrintSize(int (*p_anArray)[10]);

int main(void) {
    int myArray[10];
    printf("%d
"
, sizeof(myArray)); /* as expected 40 */
    PrintSize(&myArray);/* prints 40 */
}

void PrintSize(int (*p_anArray)[10]){
    printf("%d
"
, (int) sizeof(*p_anArray));
}

在C语言中,没有方法可以确定
未知数组的大小,因此数量需要
传递以及指向第一个元素的指针。


在C语言中,当您将数组作为参数传递给函数时,它会自动转换为指针,从一个函数传递的数组其他函数被称为call by reference。这就是被调用函数只接收指向函数第一个元素的指针的原因。这就是原因

fun(int a [])类似fun(int * a);

因此,当您打印数组的大小时,它将打印第一个元素的大小。


行为是设计的。

函数参数声明中的相同语法与局部变量定义完全不同。

原因在其他答案中描述。


在'C'编程中,languange'styof()'是运算符,并且以字节为单位返回对象的大小.'mossof()'运算符的参数必须是左值类型(整数,浮点数,结构,数组) 因此,如果你想知道一个数组的大小,你可以很简单。只需使用'sizeof()'运算符,并为他的参数使用数组名称。例如:

1
2
3
4
5
6
7
8
9
#include <stdio.h>

main(){

 int n[10];
 printf("Size of n is: %d
"
, sizeof(n));

}

32位系统的输出将是:n的大小为:40。因为32系统上的ineteger是4字节。在64x上它是8字节。在这种情况下,我们在一个数组中声明了10个整数。因此结果是'10 * sizeof(INT)"。

一些技巧:

如果我们有一个像这样声明的数组'int n [] = {1,2,3,... 155 ..};'。
所以我们想知道这个数组中存储了多少元素。
使用这个算法:

sizeof(name_of_the_array)/ sizeof(array_type)

代码:#include

主要(){

1
2
3
4
int n[] = { 1, 2, 3, 44, 6, 7 };
printf("Number of elements: %d
"
, sizeof(n) / sizeof(int));
return 0;

}


数组只是松散的大小。在大多数情况下,数组是指向内存的指针。声明中的大小只告诉编译器为数组分配多少内存 - 它与类型无关,因此sizeof()没有任何内容可以继续。