数组传参的问题
来源:百度文库 编辑:神马文学网 时间:2024/04/29 08:50:00
#include
using namespace std;
void Test( char array[20] )
{
cout << sizeof(array) << endl; // 输出 4
}
void main( void )
{
char array[20] = { 0 };
cout << sizeof(array) << endl; // 输出 20
Test( array );
}
为什么同样申明的array一个输出20一个输出4?有没高人讲得详细些?最好讲讲原理,谢谢~ 问题点数:20、回复次数:17Top
Flood1984(峰子)(好男人 灌就灌出个模样)回复于 2005-12-23 12:43:51 得分 5
数组名的蜕化
数组在作为函数参数时,数组名将蜕化为指针。书上为什么这么说呢?书上的意思是说这家伙已经蜕化得不知道自己有几个元素了。举个例子:
void fun(char array[5]);
在编译时编译器会当成是:void fun(char *array);你在这个函数中使用sizeof(a)得到的值是4,而在定义char array[5]的函数中sizeof(array) = 5,说明确实已经蜕化为指针了。所以你写:
char *pa = array ; //正确,指针到指针
数组名退化为指针,在这里强调一下:数组的元素类型仍然存在!这里要注意的是多维数组的情况。
以2维数组为例:
void fun2(char arrayMulti[3][5]);
那么在函数fun2中,arrayMulti蜕化成的是char (*)[5],即:指向char[5]类型的指针,因为前面分析过arrayMulti的元素的类型是char[5],所以在程序中:
char **pm = arrayMulti ; //错误:从char (*)[5]到 char **的赋值
char (*pm5)[5] ;
pm5 = arrayMulti ; //正确。
Top
bm1408(向va_list学习~不用VC好多年~)回复于 2005-12-23 12:44:40 得分 0
这个问题最近问的太多了~
当数组作为函接参数时,会退化为同类型的指针~Top
bm1408(向va_list学习~不用VC好多年~)回复于 2005-12-23 12:46:05 得分 0
你真快,还打了这么多字~Top
oyljerry(【勇敢的心】→ ㊣提拉米苏√㊣)回复于 2005-12-23 13:00:09 得分 0
数组作为参数时 decay成指针了Top
hsuyuan(一切无法解释的问题都是人品问题)回复于 2005-12-23 13:43:22 得分 0
2楼不光正解而且透彻Top
whyglinux(山青水秀)回复于 2005-12-23 14:35:32 得分 10
>> 数组在作为函数参数时,数组名将蜕化为指针。书上为什么这么说呢?书上的意思是说这家伙已经蜕化得不知道自己有几个元素了。
很形象,也抓住了重点。
其实根据标准的规定,不仅仅是数组在作为函数参数时数组名将退化为指针——除了作为sizeof和&的操作数之外,在表达式中出现的数组名都不知道自己有几个元素,所以这时它的类型已经不再是数组类型了,而是decay为一个指针。
举例说明:
int a[10]; // 定义 a 的类型为 int[10],数组类型
int* p = a; // a 的类型为 int*,指针类型,不再是数组类型。
a[0] = 0; // a 的类型为 int*,指针类型,不再是数组类型。并且 a[0] = *(a+0) = *a。
sizeof( a ); // a 的类型为 int[10],数组类型。
p = &a; // a 的类型为 int[10],数组类型。因此,&a 的类型为int (*)[10],是指针类型,但是跟 p 的指针类型(int*)不匹配,因此赋值非法。
总之,只要排除了sizeof和&这两种情况,在程序中把数组名作为指针来使用就是了,而且是一个指向数组首元素的指针(即数组名代表的值就是数组第一个元素的地址)。Top
beijibingshan(Zealot)回复于 2005-12-23 14:38:17 得分 0
都很快阿Top
iamcaicainiao(老菜 ◆无为莫千钧●恨水梦少白▼)回复于 2005-12-23 15:06:59 得分 0
计算内存容量
用运算符sizeof可以计算出数组的容量(字节数)。示例7-3-3(a)中,sizeof(a)的值是12(注意别忘了’\0’)。指针p指向a,但是sizeof(p)的值却是4。这是因为sizeof(p)得到的是一个指针变量的字节数,相当于sizeof(char*),而不是p所指的内存容量。C++/C语言没有办法知道指针所指的内存容量,除非在申请内存时记住它。
注意当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针。示例7-3-3(b)中,不论数组a的容量是多少,sizeof(a)始终等于sizeof(char *)。
char a[] = "hello world";
char *p = a;
cout<< sizeof(a) << endl; // 12字节
cout<< sizeof(p) << endl; // 4字节
示例7-3-3(a) 计算数组和指针的内存容量
void Func(char a[100])
{
cout<< sizeof(a) << endl; // 4字节而不是100字节
}
示例7-3-3(b) 数组退化为指针
Top
megaboy(飞天御剑流之杀神一刀斩)回复于 2005-12-23 15:32:20 得分 5
形参中的array type和incomplete type会被转换为pointer type,之所以会有这个转换,是由于ansi committee认为,如果把整个数组传递给被调函数,效率太低,从提高效率着想,一律把形参中的array type和incomplete type转换为pointer type。
要注意的是,这里涉及的是两种有差别的转换,以你的例子来说明:
对于main中的代码:
char array[20] = { 0 };
cout << sizeof(array) << endl; // 输出 20
Test( array );
array首先被定义为char[20]类型,然后作为实参传递给Test的时候,array首先被完全求值,其类型在表达式求值的过程中被临时转换为char*类型,这只是表达式计算过程中的需要而临时转换,array的类型本质上并没有被转换为char*,也就是说,Test(array)运行完后,array的类型仍然是char[20],而不会因此变成char*。
而形参中的转换跟以上转换又有一点不同,就是,虽然你在形参中写上
void Test( char array[20] )
但array并没有先定义为一个数组再转换类型,就是虽然你是以char array[20]这样写的,但这个数组并没有进行定义,而是直接从形式上把array的类型看作char*,实际被定义的对象是char*类型,不存在char[20]类型,这种转换更准确地说应该是“看作”,因为没有array type的实体被转换,array从来没有以一个数组出现过,因此在Test内部,sizeof(array)是一个指针的大小。同时,常数20被忽略。Top
whyglinux(山青水秀)回复于 2005-12-23 16:33:03 得分 0
To megaboy
>> 也就是说,Test(array)运行完后,array的类型仍然是char[20],而不会因此变成char*。
这样说不太准确。
因为数组名其实有两种身份:数组和指针。到底数组名作何解释,这要取决于数组名所处的上下文(context)环境:如果数组名是sizeof或者&的操作数,那么数组名是数组类型;否则,数组名就变成(或者说退化为、转换为)指针类型。
“橘生淮南则为橘,橘生淮北而为枳”,强调的就是环境因素对事物影响的重要性。Top
khyang(天佑)回复于 2005-12-23 21:33:15 得分 0
数组名和指针有很大区别,在使用时要进行正确区分,其区分规则如下:
规则1 数组名指代一种数据结构,这种数据结构就是数组;
例如:
char str[10];
char *pStr = str;
cout << sizeof(str) << endl;
cout << sizeof(pStr) << endl;
输出结果为:
10
4
这说明数组名str指代数据结构char[10]。
规则2 数组名可以转换为指向其指代实体的指针,而且是一个指针常量,不能作自增、自减等操作,不能被修改;
char str[10];
char *pStr = str;
str++; //编译出错,提示str不是左值
pStr++; //编译正确
规则3 指向数组的指针则是另外一种变量类型(在WIN32平台下,长度为4),仅仅意味着数组的存放地址;
规则4 数组名作为函数形参时,在函数体内,其失去了本身的内涵,仅仅只是一个指针;很遗憾,在失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等操作,可以被修改。
例如:
void arrayTest(char str[])
{
cout << sizeof(str) << endl; //输出指针长度
str++; //编译正确
}
int main(int argc, char* argv[])
{
char str1[10] = "I Love U";
arrayTest(str1);
return 0;
}Top
iicup(双杯献酒)回复于 2005-12-23 22:39:58 得分 0
增长知识了.Top
huihuixong(狼尾巴)回复于 2005-12-23 23:16:03 得分 0
解释的很完整,,,Top
vollin(林尚义)回复于 2005-12-24 00:17:09 得分 0
这样就行了
template
void Test( _Ty& array)
{
cout << sizeof(array) << endl;
}
int main(int argc, char* argv[])
{
char array[20] = { 0 };
cout << sizeof(array) << endl; // 输出 20
Test(array);// 输出 20
return 0;
}
using namespace std;
void Test( char array[20] )
{
cout << sizeof(array) << endl; // 输出 4
}
void main( void )
{
char array[20] = { 0 };
cout << sizeof(array) << endl; // 输出 20
Test( array );
}
为什么同样申明的array一个输出20一个输出4?有没高人讲得详细些?最好讲讲原理,谢谢~ 问题点数:20、回复次数:17Top
Flood1984(峰子)(好男人 灌就灌出个模样)回复于 2005-12-23 12:43:51 得分 5
数组名的蜕化
数组在作为函数参数时,数组名将蜕化为指针。书上为什么这么说呢?书上的意思是说这家伙已经蜕化得不知道自己有几个元素了。举个例子:
void fun(char array[5]);
在编译时编译器会当成是:void fun(char *array);你在这个函数中使用sizeof(a)得到的值是4,而在定义char array[5]的函数中sizeof(array) = 5,说明确实已经蜕化为指针了。所以你写:
char *pa = array ; //正确,指针到指针
数组名退化为指针,在这里强调一下:数组的元素类型仍然存在!这里要注意的是多维数组的情况。
以2维数组为例:
void fun2(char arrayMulti[3][5]);
那么在函数fun2中,arrayMulti蜕化成的是char (*)[5],即:指向char[5]类型的指针,因为前面分析过arrayMulti的元素的类型是char[5],所以在程序中:
char **pm = arrayMulti ; //错误:从char (*)[5]到 char **的赋值
char (*pm5)[5] ;
pm5 = arrayMulti ; //正确。
Top
bm1408(向va_list学习~不用VC好多年~)回复于 2005-12-23 12:44:40 得分 0
这个问题最近问的太多了~
当数组作为函接参数时,会退化为同类型的指针~Top
bm1408(向va_list学习~不用VC好多年~)回复于 2005-12-23 12:46:05 得分 0
你真快,还打了这么多字~Top
oyljerry(【勇敢的心】→ ㊣提拉米苏√㊣)回复于 2005-12-23 13:00:09 得分 0
数组作为参数时 decay成指针了Top
hsuyuan(一切无法解释的问题都是人品问题)回复于 2005-12-23 13:43:22 得分 0
2楼不光正解而且透彻Top
whyglinux(山青水秀)回复于 2005-12-23 14:35:32 得分 10
>> 数组在作为函数参数时,数组名将蜕化为指针。书上为什么这么说呢?书上的意思是说这家伙已经蜕化得不知道自己有几个元素了。
很形象,也抓住了重点。
其实根据标准的规定,不仅仅是数组在作为函数参数时数组名将退化为指针——除了作为sizeof和&的操作数之外,在表达式中出现的数组名都不知道自己有几个元素,所以这时它的类型已经不再是数组类型了,而是decay为一个指针。
举例说明:
int a[10]; // 定义 a 的类型为 int[10],数组类型
int* p = a; // a 的类型为 int*,指针类型,不再是数组类型。
a[0] = 0; // a 的类型为 int*,指针类型,不再是数组类型。并且 a[0] = *(a+0) = *a。
sizeof( a ); // a 的类型为 int[10],数组类型。
p = &a; // a 的类型为 int[10],数组类型。因此,&a 的类型为int (*)[10],是指针类型,但是跟 p 的指针类型(int*)不匹配,因此赋值非法。
总之,只要排除了sizeof和&这两种情况,在程序中把数组名作为指针来使用就是了,而且是一个指向数组首元素的指针(即数组名代表的值就是数组第一个元素的地址)。Top
beijibingshan(Zealot)回复于 2005-12-23 14:38:17 得分 0
都很快阿Top
iamcaicainiao(老菜 ◆无为莫千钧●恨水梦少白▼)回复于 2005-12-23 15:06:59 得分 0
计算内存容量
用运算符sizeof可以计算出数组的容量(字节数)。示例7-3-3(a)中,sizeof(a)的值是12(注意别忘了’\0’)。指针p指向a,但是sizeof(p)的值却是4。这是因为sizeof(p)得到的是一个指针变量的字节数,相当于sizeof(char*),而不是p所指的内存容量。C++/C语言没有办法知道指针所指的内存容量,除非在申请内存时记住它。
注意当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针。示例7-3-3(b)中,不论数组a的容量是多少,sizeof(a)始终等于sizeof(char *)。
char a[] = "hello world";
char *p = a;
cout<< sizeof(a) << endl; // 12字节
cout<< sizeof(p) << endl; // 4字节
示例7-3-3(a) 计算数组和指针的内存容量
void Func(char a[100])
{
cout<< sizeof(a) << endl; // 4字节而不是100字节
}
示例7-3-3(b) 数组退化为指针
Top
megaboy(飞天御剑流之杀神一刀斩)回复于 2005-12-23 15:32:20 得分 5
形参中的array type和incomplete type会被转换为pointer type,之所以会有这个转换,是由于ansi committee认为,如果把整个数组传递给被调函数,效率太低,从提高效率着想,一律把形参中的array type和incomplete type转换为pointer type。
要注意的是,这里涉及的是两种有差别的转换,以你的例子来说明:
对于main中的代码:
char array[20] = { 0 };
cout << sizeof(array) << endl; // 输出 20
Test( array );
array首先被定义为char[20]类型,然后作为实参传递给Test的时候,array首先被完全求值,其类型在表达式求值的过程中被临时转换为char*类型,这只是表达式计算过程中的需要而临时转换,array的类型本质上并没有被转换为char*,也就是说,Test(array)运行完后,array的类型仍然是char[20],而不会因此变成char*。
而形参中的转换跟以上转换又有一点不同,就是,虽然你在形参中写上
void Test( char array[20] )
但array并没有先定义为一个数组再转换类型,就是虽然你是以char array[20]这样写的,但这个数组并没有进行定义,而是直接从形式上把array的类型看作char*,实际被定义的对象是char*类型,不存在char[20]类型,这种转换更准确地说应该是“看作”,因为没有array type的实体被转换,array从来没有以一个数组出现过,因此在Test内部,sizeof(array)是一个指针的大小。同时,常数20被忽略。Top
whyglinux(山青水秀)回复于 2005-12-23 16:33:03 得分 0
To megaboy
>> 也就是说,Test(array)运行完后,array的类型仍然是char[20],而不会因此变成char*。
这样说不太准确。
因为数组名其实有两种身份:数组和指针。到底数组名作何解释,这要取决于数组名所处的上下文(context)环境:如果数组名是sizeof或者&的操作数,那么数组名是数组类型;否则,数组名就变成(或者说退化为、转换为)指针类型。
“橘生淮南则为橘,橘生淮北而为枳”,强调的就是环境因素对事物影响的重要性。Top
khyang(天佑)回复于 2005-12-23 21:33:15 得分 0
数组名和指针有很大区别,在使用时要进行正确区分,其区分规则如下:
规则1 数组名指代一种数据结构,这种数据结构就是数组;
例如:
char str[10];
char *pStr = str;
cout << sizeof(str) << endl;
cout << sizeof(pStr) << endl;
输出结果为:
10
4
这说明数组名str指代数据结构char[10]。
规则2 数组名可以转换为指向其指代实体的指针,而且是一个指针常量,不能作自增、自减等操作,不能被修改;
char str[10];
char *pStr = str;
str++; //编译出错,提示str不是左值
pStr++; //编译正确
规则3 指向数组的指针则是另外一种变量类型(在WIN32平台下,长度为4),仅仅意味着数组的存放地址;
规则4 数组名作为函数形参时,在函数体内,其失去了本身的内涵,仅仅只是一个指针;很遗憾,在失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等操作,可以被修改。
例如:
void arrayTest(char str[])
{
cout << sizeof(str) << endl; //输出指针长度
str++; //编译正确
}
int main(int argc, char* argv[])
{
char str1[10] = "I Love U";
arrayTest(str1);
return 0;
}Top
iicup(双杯献酒)回复于 2005-12-23 22:39:58 得分 0
增长知识了.Top
huihuixong(狼尾巴)回复于 2005-12-23 23:16:03 得分 0
解释的很完整,,,Top
vollin(林尚义)回复于 2005-12-24 00:17:09 得分 0
这样就行了
template
void Test( _Ty& array)
{
cout << sizeof(array) << endl;
}
int main(int argc, char* argv[])
{
char array[20] = { 0 };
cout << sizeof(array) << endl; // 输出 20
Test(array);// 输出 20
return 0;
}
数组传参的问题
数组传参的问题
谈一下C,C#的二维数组传参问题
谈一下C,C#的二维数组传参问题
指向数组的指针与多维数组
揭开C/C++中数组形参的迷雾
C/C 如何解决大数组问题?
第三章 数组的解剖学
多维数组的指针变量
如何高效的遍历数组?
使用MFC的数组类
多维数组的指针变量
vb.net的多维数组
对多维数组的理解
指针与数组的异同
第三章 数组的解剖学
CSDN技术中心 第二章 再一次吃惊----数组的数组与多维数组的区别
第二章 再一次吃惊----数组的数组与多维数组的区别 - 飞天御剑流
第五章 指向数组的指针
关于java数组的深度思考
结构体零长度数组的作用
List、Set、数组之间的转换
历史上的 Collection 类 ― 数组
关于java数组的深度思考