近来在写程序的时候遇到了一个问题,就是传递一个数组指针进入一个函数的时候,虽然指针能够顺利的传递,但是,我们无法求出该数组的大小。见下面的代码:
原因分析:
1.对于第一个输出,由于在main函数中定义的为数组,所以可以直接利用sizeof函数来求出a数组的长度。
2.对于传递参数类型,比如上面的setNum函数(未传递个数版本),此时,调用该函数的时候,a退化为一个普通的指针,也就是说,此时sizeof(p)求出来的就是一个指针的大小,除以int的大小,恰好为1.
启示:
C语言中,不能够根据一个数组指针就求出来任意一个数组的大小。解决办法就是传第一个参数进来,指定大小。
ps:参考资料(详实): http://topic.csdn.net/t/20060205/18/4540750.html
摘录:
> 如果作为函数的参数是没法求的,
> 但这样是可以的:
>
> #define LENGTH(s) (sizeof(s) / sizeof(int))
>
> int s[12];
> int length = LENGTH(s);
==================================================
这样的方法只能用于数组变量的数组名,对于指向数组的指针,以及作为参数的数组名都是没有效果的,上面已经有人解释了
》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
不可能有办法的。
当你定义一个数组的时候:
int a[] = {1, 2, 3}; // 实际上被编译为 int a[3] = {1,2,3}
数组名代表的是数组的地址。注意 —— 你绝对没有办法通过数组名动态获得数组的大小。当你丢失a的长度信息的时候,你永远不可能知道他的长度。
那么 sizeof 是怎么回事呢?他不是通过 a 的名字获得 a的大小了么? —— 大错特错!
关键字 sizeof 产生的是一个编译期常量(注1) 他的运作方式是这样的:
当你写:
sizeof a
实质是:
sizeof ( a的类型 )
而a的类型是什么呢?编译器察看 a的定义发现, 是 int [3]
就是说,这里 sizeof a 实质是:
sizeof ( int[3] )
完全等同于常量 12 (假定int为4字节)。
考虑一个函数
void func( int a[] );
// 写成 int a[3] 也不会有本质区别——也许你该试试写成 int (&a) [3] ?
C++规定,数组作为形参的时候,a代表数组首地址。
他的底层意义是: a 退化为了一个4字节的指针,没有任何变量表示数组的大小会“自动”被传递进来。
我们看看这个时候 sizeof a是什么:
sizeof( 函数形参的a[] ) = sizeof( int* const ) = 4 // 当然a[]不是合法的C++类型
仍然不服气?好——我们反问一个问题:若你是C /C++的设计者, 你怎么在兼容原有设计的基础上让void func( int a[] )同时传递地址和大小?
首先,a是一个变量,而且类似数组。他必须是一个地址,否则你不知道如何索引元素。
他怎么再带上一个变量表示他的大小呢?
扩充 sizeof (a) 的能力?
sizeof a 必须产生代码——不管是常量还是什么。 要让他在运行时决定 a的值, a就必须带上他的大小信息。
1 你必须修改C标准,让C支持“两种”数组。一种是定义处的数组,他分配大片连续内存,和原来的C标准相同。
2 另一种是作为参数传递数组。 你必须传递地址和数组大小;这个数组实际上是一个8字节的结构{ 地址; 大小}(事实上可能更加复杂,考虑多纬数组如何实现? )
3 系统必须根据两种不同数组分别实现其 []、* 、&等。 原有的数组根据其首地址偏移(这是个常量)和下标寻址; 而参数数组则首先取“地址”内容(这是个变量),然后根据这个地址寻址....
#include
<
stdio.h
>
void setNum( int * p, int a);
void setNum( int * p);
int main()
{
int a[] = {1,2,4,5};
printf("%d\n",sizeof(a)/sizeof(a[0]));
setNum(a);
}
void setNum( int * p, int a)
{
*p = a;
}
void setNum( int * p)
{
int Num = sizeof(p)/sizeof(p[0]);
printf("%d\n",Num);
}
结果是,输出分别是4和1.
void setNum( int * p, int a);
void setNum( int * p);
int main()
{
int a[] = {1,2,4,5};
printf("%d\n",sizeof(a)/sizeof(a[0]));
setNum(a);
}
void setNum( int * p, int a)
{
*p = a;
}
void setNum( int * p)
{
int Num = sizeof(p)/sizeof(p[0]);
printf("%d\n",Num);
}
原因分析:
1.对于第一个输出,由于在main函数中定义的为数组,所以可以直接利用sizeof函数来求出a数组的长度。
2.对于传递参数类型,比如上面的setNum函数(未传递个数版本),此时,调用该函数的时候,a退化为一个普通的指针,也就是说,此时sizeof(p)求出来的就是一个指针的大小,除以int的大小,恰好为1.
启示:
C语言中,不能够根据一个数组指针就求出来任意一个数组的大小。解决办法就是传第一个参数进来,指定大小。
ps:参考资料(详实): http://topic.csdn.net/t/20060205/18/4540750.html
摘录:
> 如果作为函数的参数是没法求的,
> 但这样是可以的:
>
> #define LENGTH(s) (sizeof(s) / sizeof(int))
>
> int s[12];
> int length = LENGTH(s);
==================================================
这样的方法只能用于数组变量的数组名,对于指向数组的指针,以及作为参数的数组名都是没有效果的,上面已经有人解释了
》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
不可能有办法的。
当你定义一个数组的时候:
int a[] = {1, 2, 3}; // 实际上被编译为 int a[3] = {1,2,3}
数组名代表的是数组的地址。注意 —— 你绝对没有办法通过数组名动态获得数组的大小。当你丢失a的长度信息的时候,你永远不可能知道他的长度。
那么 sizeof 是怎么回事呢?他不是通过 a 的名字获得 a的大小了么? —— 大错特错!
关键字 sizeof 产生的是一个编译期常量(注1) 他的运作方式是这样的:
当你写:
sizeof a
实质是:
sizeof ( a的类型 )
而a的类型是什么呢?编译器察看 a的定义发现, 是 int [3]
就是说,这里 sizeof a 实质是:
sizeof ( int[3] )
完全等同于常量 12 (假定int为4字节)。
考虑一个函数
void func( int a[] );
// 写成 int a[3] 也不会有本质区别——也许你该试试写成 int (&a) [3] ?
C++规定,数组作为形参的时候,a代表数组首地址。
他的底层意义是: a 退化为了一个4字节的指针,没有任何变量表示数组的大小会“自动”被传递进来。
我们看看这个时候 sizeof a是什么:
sizeof( 函数形参的a[] ) = sizeof( int* const ) = 4 // 当然a[]不是合法的C++类型
仍然不服气?好——我们反问一个问题:若你是C /C++的设计者, 你怎么在兼容原有设计的基础上让void func( int a[] )同时传递地址和大小?
首先,a是一个变量,而且类似数组。他必须是一个地址,否则你不知道如何索引元素。
他怎么再带上一个变量表示他的大小呢?
扩充 sizeof (a) 的能力?
sizeof a 必须产生代码——不管是常量还是什么。 要让他在运行时决定 a的值, a就必须带上他的大小信息。
1 你必须修改C标准,让C支持“两种”数组。一种是定义处的数组,他分配大片连续内存,和原来的C标准相同。
2 另一种是作为参数传递数组。 你必须传递地址和数组大小;这个数组实际上是一个8字节的结构{ 地址; 大小}(事实上可能更加复杂,考虑多纬数组如何实现? )
3 系统必须根据两种不同数组分别实现其 []、* 、&等。 原有的数组根据其首地址偏移(这是个常量)和下标寻址; 而参数数组则首先取“地址”内容(这是个变量),然后根据这个地址寻址....