为什么作为参数发送的数组的大小与main中的相同?
#includevoid PrintSize(int p_someArray[10]); int main () { int myArray[10]; printf("%d\n", sizeof(myArray)); /* As expected, 40 */ PrintSize(myArray);/* Prints 4, not 40 */ } void PrintSize(int p_someArray[10]){ printf("%d\n", sizeof(p_someArray)); }
Prasoon Saur.. 100
将数组类型传递给函数时,会隐式转换为指针类型.
所以,
void PrintSize(int p_someArray[10]) { printf("%zu\n", sizeof(p_someArray)); }
和
void PrintSize(int *p_someArray) { printf("%zu\n", sizeof(p_someArray)); }
是等价的.所以你得到的是价值sizeof(int*)
将数组类型传递给函数时,会隐式转换为指针类型.
所以,
void PrintSize(int p_someArray[10]) { printf("%zu\n", sizeof(p_someArray)); }
和
void PrintSize(int *p_someArray) { printf("%zu\n", sizeof(p_someArray)); }
是等价的.所以你得到的是价值sizeof(int*)
它是一个指针,这就是为什么它是一个常见的实现,将数组的大小作为第二个参数传递给函数
正如其他人所说,当用作函数参数时,数组会衰减到指向第一个元素的指针.还值得注意的是,sizeof不评估表达式,并且在与表达式一起使用时不需要括号,因此您的参数实际上根本不被使用,因此您也可以使用类型而不是值来编写sizeof.
#includevoid PrintSize1 ( int someArray[][10] ); void PrintSize2 ( int someArray[10] ); int main () { int myArray[10]; printf ( "%d\n", sizeof myArray ); /* as expected 40 */ printf ( "%d\n", 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\n", sizeof someArray[0] ); } void PrintSize2 ( int someArray[10] ) { printf ( "%d\n", sizeof ( int[10] ) ); }
因此,您需要将数组的长度作为第二个参数传递.当您编写代码时,您既要声明一个常量大小的数组,然后将该数组传递给函数,那么让数组长度常量显示在代码中的几个位置是很痛苦的...
K&R救援:
#define N_ELEMENTS(array) (sizeof(array)/sizeof((array)[0]))
所以现在你可以这样做:
int a[10]; ... myfunction(a, N_ELEMENTS(a));
因为数组在作为参数传递时会衰减为指针.这就是C的工作原理,尽管你可以通过引用传递C++中的"数组"并克服这个问题.请注意,您可以将不同大小的数组传递给此函数:
// 10 is superfluous here! You can pass an array of different size! void PrintSize(int p_someArray[10]);
你发现的行为实际上是C语言中的一个大问题.每当您声明一个带有数组参数的函数时,编译器都会忽略您并将参数更改为指针.所以这些声明都表现得像第一个:
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的目的):
struct array_rly { int a[5]; }; void func(struct array_rly a) { printf("%zd\n", sizeof(a.a)/sizeof(a.a[0])); /* prints 5 */ }
或者通过传递指向数组的指针:
void func(const int (*a)[5]) { printf("%zd\n", sizeof(*a)/sizeof((*a)[0])); /* prints 5 */ }
如果数组大小不是编译时常量,则可以将指针到数组技术与C99可变长度数组一起使用:
void func(int n, const int (*a)[n]) { printf("%zd\n", sizeof(*a)/sizeof((*a)[0])); /* prints n */ }