#include "stdio.h"
#define COUNT(a) (sizeof(a) / sizeof(*(a)))
void test(int b[]) {
printf("2, count:%d\n", COUNT(b));
}
int main(void) {
int a[] = { 1,2,3 };
printf("1, count:%d\n", COUNT(a));
test(a);
return 0;
}
结果很明显:
1, count:3
2, count:1
我的问题:
答案 0 :(得分:7)
C语言中没有“数组指针”这样的东西。
尺寸不存储在任何地方。 a
不是指针,a
是int[3]
类型的对象,这是编译器在编译时熟知的事实。因此,当您要求编译器在编译时计算sizeof(a) / sizeof(*a)
时,编译器知道答案是3
。
当您将a
传递给函数时,您有意要求编译器将数组类型转换为指针类型(因为您将函数参数声明为指针)。对于指针,您的sizeof
表达式会产生完全不同的结果。
答案 1 :(得分:5)
- 声明“a”时存储的长度(计数/大小)信息在哪里?
醇>
它没有存储在任何地方。 sizeof
运算符(在COUNT()
宏中使用)返回整个数组的大小,当它被赋予一个真实数组作为操作数时(就像它在第一个printf()
中)
- 当“a”传递给test()函数时,为什么长度(计数/大小)信息会丢失?
醇>
不幸的是,在C中,函数的数组参数是虚构的。数组不会传递给函数;该参数被视为一个指针,并且在函数调用中传递的数组参数被“衰减”为一个简单的指针。 sizeof
运算符返回指针的大小,该大小与用作参数的数组的大小无关。
作为旁注,在C ++中,您可以将一个函数参数作为数组的引用,在这种情况下,完整的数组类型可供该函数使用(即,参数没有不会衰减到指针,sizeof
将返回完整数组的大小)。但是,在这种情况下,参数必须与数组类型完全匹配(包括元素数),这使得该技术最常用于模板。
例如,以下C ++程序将按预期执行:
#include "stdio.h"
#define COUNT(a) (sizeof(a) / sizeof(*(a)))
template <int T>
void test(int (&b)[T]) {
printf("2, count:%d\n", COUNT(b));
}
int main(int argc, char *argv[]) {
int a[] = { 1,2,3 };
printf("1, count:%d\n", COUNT(a));
test(a);
return 0;
}
答案 2 :(得分:1)
当您在main()
中引用数组时,实际的数组声明定义是可见的,因此sizeof(a)
以字节为单位给出数组的大小。
当你在函数中引用数组时,参数实际上是'void test(int *b)
,并且指针的大小除以它指向的东西的大小恰好在32位平台上为1而在具有LP64架构的64位平台上(或者,实际上,在像Windows-64这样的LLP64平台上)它将是2,因为指针是8个字节而int
是4个字节。
没有通用的方法来确定传递给函数的数组的大小;你必须明确地和手动地传递它。
来自评论:
我还有两个问题:
- 你是什么意思“......实际的声明是可见的......”?编译器(或OS)可以通过sizeof(a)函数得到长度信息吗?
- 为什么指针&amp;(a [0])不包含长度信息作为指针“a”?
醇>
我认为你在学习C或其他更现代的语言之前学过Java。最终,它归结为“因为这是C定义的方式”。操作系统不涉及;这是一个纯粹的编译器问题。
sizeof()
是一个运算符,而不是一个函数。除非您正在处理VLA(可变长度数组),否则它将在编译时进行求值并且是一个常量值。在main()
里面,数组定义(当我说'声明'时我错过了),当sizeof()
运算符应用于实际数组的名称时 - 而不是数组函数的参数 - 然后返回的大小是以字节为单位的数组大小。
因为这是C而不是Algol,Pascal,Java,C#,......
C不存储数组的大小 - 句点。这是生活中的事实。并且,当数组传递给函数时,大小信息不会传递给函数;数组'衰减'到指向数组的第0个元素的指针 - 只传递该指针。
答案 3 :(得分:1)
- 声明“a”时存储的长度(计数/大小)信息在哪里?
醇>
无处。这个问题没有意义BTW。
- 当“a”传递给test()函数时,为什么长度(计数/大小)信息会丢失?
醇>
传递给函数时,数组衰减为指针(指向第一个元素)。所以答案是'无处',与上一个问题类似,这个问题再没有任何意义。
答案 4 :(得分:1)
1. Where is the length(count/size) info stored when "a" is declared?
未存储。编译器知道它是什么,因此知道它的大小。因此编译器可以用实际大小替换sizeof()
。
2. Why is the length(count/size) info lost when "a" is passed to the test() function?
在这种情况下,b被声明为指针(即使它可能指向a)。给定一个指针,编译器不知道指向的数据的大小。
答案 5 :(得分:0)
数组指针不存储大小。但是,[]
类型实际上不是指针。这是一种不同的类型。当你说int a[] = {1,2,3};
时你定义了3个元素的数组,并且由于它是这样定义的,sizeof(a)给出了整个数组的大小。
然而,当你将参数声明为int a []时,它与int * a几乎相同,而sizeof(a)将是指针的大小(它恰好可能与{{1}的大小相同}}, 但不总是)。
在C中,无法将大小存储在指针类型中,因此如果需要大小,则必须将其作为附加参数传递或使用int
。