数组名与指针

xumin111050 2014-04-24 09:26:18
#include <iostream>
using namespace std;

void arrayTest(char str[])
{
cout << sizeof(str) << endl;
cout<<"**"<<str++<<"**"<<endl;
}

int main(int argc, char* argv[])
{
char str1[10] = "I Love U";
arrayTest(str1);
return 0;
}

输出结果为
4
**I Love U**
4是c++中规定的指针地址长度,说明形参传值时,把数组名当做了指针
另外,str可++,说明不再受“指针常量的约束”
最后输出了整个字符串,又说明,其值就是这个数组的内容

感觉彻底混乱了,有没有人解释一下
...全文
372 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
xumin111050 2014-05-06
  • 打赏
  • 举报
回复
@all,最近在忙其他的事,没及时回复各位,受教了
幻夢之葉 2014-04-29
  • 打赏
  • 举报
回复
就是char* ,cout其内容,其他cout地址
unituniverse2 2014-04-29
  • 打赏
  • 举报
回复
自己的帖子没法编辑,又改了一下,这次应该看的更清楚:

#include <conio.h>
#include <stdio.h>
#include <iostream>


void foo1(char * p)
{
	std::cout << sizeof(p) << std::endl;
}

void foo2(char str [])
{
	std::cout << sizeof(str) << std::endl;
}

void foo3(char (& str)[10])
{
	std::cout << sizeof(str) << std::endl;
}

template < typename > struct Is_Array { enum nRes { val }; };

template < typename ElementType, size_t Nx >
struct Is_Array< ElementType[Nx] >
{
	enum nRes { val = 1 };
};

template < typename ElementType, size_t Nx >
struct Is_Array< ElementType (&)[Nx] >
{
	enum nRes { val = 1 };
};

template < typename ElementType, size_t Nx >
struct Is_Array< ElementType (&&)[Nx] >
{
	enum nRes { val = 1 };
};

template < typename My_Type >
void foo4(My_Type && raw_arg)
{
	std::cout << sizeof(raw_arg) << std::endl;
	std::cout << "The 'raw_arg' " << (Is_Array<decltype(raw_arg)>::val ? "is" : "isn't") << " an array!" << std::endl;
}

template < typename My_Type >
void foo5(My_Type arg [])
{
	std::cout << sizeof(arg) << std::endl;
	std::cout << "The 'arg' " << (Is_Array<decltype(arg)>::val ? "is" : "isn't") << " an array!" << std::endl;
}

template < typename My_Type >
void foo6(My_Type arg)
{
	std::cout << sizeof(arg) << std::endl;
	std::cout << "The 'arg' " << (Is_Array<decltype(arg)>::val ? "is" : "isn't") << " an array!" << std::endl;
}

int main(void)
{
	char a[10] = "";

	foo1(a);
	std::cout << "--------" << std::endl;
	foo2(a);
	std::cout << "--------" << std::endl;
	foo3(a);
	std::cout << "--------" << std::endl;
	foo4(a);
	std::cout << "--------" << std::endl;
	foo4((char *)a);
	std::cout << "--------" << std::endl;
	foo5(a);
	std::cout << "--------" << std::endl;
	foo6(a);

	_getch();
	return(0);
}
unituniverse2 2014-04-29
  • 打赏
  • 举报
回复
其实上面的代码有点不合理(做了个参数都为引用的假定),又改了一下

#include <conio.h>
#include <stdio.h>
#include <iostream>


void foo1(char * p)
{
	std::cout << sizeof(p) << std::endl;
}

void foo2(char str [])
{
	std::cout << sizeof(str) << std::endl;
}

void foo3(char (& str)[10])
{
	std::cout << sizeof(str) << std::endl;
}

template < typename > struct Is_Array { enum nRes { val }; };

template < typename ElementType, size_t Nx >
struct Is_Array< ElementType[Nx] >
{
	enum nRes { val = 1 };
};

template < typename ElementType, size_t Nx >
struct Is_Array< ElementType (&)[Nx] >
{
	enum nRes { val = 1 };
};

template < typename ElementType, size_t Nx >
struct Is_Array< ElementType (&&)[Nx] >
{
	enum nRes { val = 1 };
};

template < typename My_Type >
void foo4(My_Type && raw_arg)
{
	std::cout << sizeof(raw_arg) << std::endl;
	std::cout << "The 'raw_arg' " << (Is_Array<My_Type &>::val ? "is" : "isn't") << " an array!" << std::endl;
}

template < typename My_Type >
void foo5(My_Type arg [])
{
	std::cout << sizeof(arg) << std::endl;
	std::cout << "The 'arg' " << (Is_Array<My_Type &>::val ? "is" : "isn't") << " an array!" << std::endl;
}

template < typename My_Type >
void foo6(My_Type arg)
{
	std::cout << sizeof(arg) << std::endl;
	std::cout << "The 'arg' " << (Is_Array<My_Type &>::val ? "is" : "isn't") << " an array!" << std::endl;
}

int main(void)
{
	char a[10] = "";

	foo1(a);
	std::cout << "--------" << std::endl;
	foo2(a);
	std::cout << "--------" << std::endl;
	foo3(a);
	std::cout << "--------" << std::endl;
	foo4(a);
	std::cout << "--------" << std::endl;
	foo4((char *)a);
	std::cout << "--------" << std::endl;
	foo5(a);
	std::cout << "--------" << std::endl;
	foo6(a);

	_getch();
	return(0);
}

不过应该是无所谓的,我们都知道作为函数参数的时候数组在C/C++中不能按值传递(全部内容,而不是仅仅首地址)。
unituniverse2 2014-04-29
  • 打赏
  • 举报
回复
楼主可以试试这段代码:

#include <conio.h>
#include <stdio.h>
#include <iostream>


void foo1(char * p)
{
	std::cout << sizeof(p) << std::endl;
}

void foo2(char str [])
{
	std::cout << sizeof(str) << std::endl;
}

void foo3(char (& str)[10])
{
	std::cout << sizeof(str) << std::endl;
}

template < typename > struct Is_Array { enum nRes { val }; };

template < typename ElementType, size_t Nx >
struct Is_Array< ElementType (&)[Nx] >
{
	enum nRes { val = 1 };
};

template < typename ElementType, size_t Nx >
struct Is_Array< ElementType (&&)[Nx] >
{
	enum nRes { val = 1 };
};

template < typename My_Type >
void foo4(My_Type && raw_arg)
{
	std::cout << sizeof(raw_arg) << std::endl;
	std::cout << "The 'raw_arg' " << (Is_Array<My_Type &>::val ? "is" : "isn't") << " an array!" << std::endl;
}

template < typename My_Type >
void foo5(My_Type arg [])
{
	std::cout << "The 'arg' " << (Is_Array<My_Type &>::val ? "is" : "isn't") << " an array!" << std::endl;
}

int main(void)
{
	char a[10] = "";

	foo1(a);
	std::cout << "--------" << std::endl;
	foo2(a);
	std::cout << "--------" << std::endl;
	foo3(a);
	std::cout << "--------" << std::endl;
	foo4(a);
	std::cout << "--------" << std::endl;
	foo4((char *)a);
	std::cout << "--------" << std::endl;
	foo5(a);

	_getch();
	return(0);
}

最后使用的模板,是为了公平起见(貌似也找不到方便的不用模板就能说明问题的方法)。因为考虑到可能有些人会问“你这foo3不是故意用了数组吗?那当然又可以得到长度了”这类问题。 使用foo4,捕捉到的参数raw_arg因为在这个模板未实例化时事先只是个“未知”类型,而类模板(Is_Array)匹配特化时不像函数模板那样承认隐式转换的结果(最后那个foo4的调用可以证明这一点),这样就可以看看raw_arg的原始类型到底是什么。
z_bo 2014-04-29
  • 打赏
  • 举报
回复
引用 19 楼 mikeboy91 的回复:
sizeof()从来都是类型长度,要整个字符串长度,可用string a = str ; a.size();
sizeof(arrayName) == arrayLength
赵4老师 2014-04-29
  • 打赏
  • 举报
回复
乍看起来c++的cin、cout在输入、输出上比c的scanf、printf简单,不用格式控制符! 但是不用格式控制符,输入输出恰好是你期望的格式的时候好说;等到输入输出不是你期望的格式的时候,你就会觉得还是用格式控制符更方便、更靠谱。 摒弃cin、cout! 使用scanf、printf。
mikeboy91 2014-04-29
  • 打赏
  • 举报
回复
sizeof()从来都是类型长度,要整个字符串长度,可用string a = str ; a.size();
「已注销」 2014-04-29
  • 打赏
  • 举报
回复
#include <iostream>
using namespace std;

void arrayTest(char str[])
{
     cout << sizeof(str) << endl;
 	cout<<"**"<<str++<<"**"<<endl;//运算符重载,可以自加是因为这个不是指向常量的指针,是你把一个数组的地址赋值给了一个普通指针
}

int main(int argc, char* argv[])
{
char str1[10] = "I Love U";
arrayTest(str1); 
return 0;
}
#include <iostream>
using namespace std;

void arrayTest(char *const str)
{
     cout << sizeof(str) << endl;
 	cout<<"**"<<str<<"**"<<endl;
}

int main(int argc, char* argv[])
{
char str1[10] = "I Love U";
arrayTest(str1); 
return 0;
}
光之后裔 2014-04-28
  • 打赏
  • 举报
回复
代码写作:cout<<"**"<<++str<<"**"<<endl; 输出结果就变了: 4 ** Love U**(更正)
光之后裔 2014-04-28
  • 打赏
  • 举报
回复
代码:cout<<"**"<<str++<<"**"<<endl;//去掉自增运算++没问题 写作:cout<<"**"<<str<<"**"<<endl; 输出结果依然是 4 **I Love U** 因为先执行cout<<str,再执行str+1; 但代码写作:cout<<"**"<<++str<<"**"<<endl; 输出结果就变了: 4 **ILove U** 因为先执行了str+1,再执行cout<<str 还有str就是字符串首地址,占一个字长空间,一般是四个字节所以sizeof(str)=4,str也可以执行自增运算
mujiok2003 2014-04-25
  • 打赏
  • 举报
回复
引用 10 楼 PDD123 的回复:
应该说代码都是我写的,导出的是这样写: _declspec(dllexport) void testfun(char str[]); 导入的时候是这样写: _declspec(dllimport) void testfun(char str[]); 结果反编译来看,两个函数接口的名字都变成void __cdecl testfun(char * const)这样了。虽然我知道这只是一个名字,叫啥都不影响,但是为何会加上了const修饰呢?
奇怪的msvc,你可以向ms开发团队提问
Botroskey 2014-04-25
  • 打赏
  • 举报
回复
数组名传进函数,会丢失数组长度的信息,数组名也就退化成了一个指针,这个指针指向数组的首地址,不同的是在函数里面并不清楚这个指针指向的内存块有多大。 既然退化成了一个指针,指针当然有++的运算功能,至于为什么”不再受’指针常量的约束‘ “,是因为你原来的
	char str1[10] = "I Love U";
在执行上面这段代码的时候,编译器会把文字常量区里面的这段字符串拷贝出来,复制到编译器分配给str1数组的内存当中去,注意这是后str1所指向的内存并非一个常量,也就不存在什么指向常量的指针 ”输出了整个字符串“,在函数中,str退化成了一个char*的指针,在main函数里面,上面也讲到了会把文字常量区里面的这段字符串拷贝出来,复制到编译器分配给str1数组的内存当中去,那么字符串里面的'\0'也复制过去了,在<<输出运算符遇到该字符串结尾符的时候就停止输出后面内存中的内容了。 说的有点乱,见谅,不过大体意思到了
不要做咸鱼 2014-04-25
  • 打赏
  • 举报
回复
数组名作为参数 这个数组会退化成指针的
PDD123 2014-04-25
  • 打赏
  • 举报
回复
我错了,我想明白了,我记反了。 *后面有const是修饰指针本身的,在前面才是修饰指针指向的空间的。
PDD123 2014-04-25
  • 打赏
  • 举报
回复
应该说代码都是我写的,导出的是这样写: _declspec(dllexport) void testfun(char str[]); 导入的时候是这样写: _declspec(dllimport) void testfun(char str[]); 结果反编译来看,两个函数接口的名字都变成void __cdecl testfun(char * const)这样了。虽然我知道这只是一个名字,叫啥都不影响,但是为何会加上了const修饰呢?
PDD123 2014-04-25
  • 打赏
  • 举报
回复
引用 7 楼 mujiok2003 的回复:
[quote=引用 6 楼 PDD123 的回复:] [quote=引用 3 楼 mujiok2003 的回复:]
void arrayTest(char str[])
其实是

void arrayTest(char *str)
, 不要被它的外表欺骗了。
本来我也觉得是这样,但是我写了DLL然后导入,然后反编译看了看导入函数的名字,结果发现很奇怪:
//.h
_declspec(dllexport)  void testfun(char str[]);
//.cpp
void testfun(char str[])
{
	str[0]=1;
	return;
}
导入函数为什么是 extrn __declspec(dllimport) void __cdecl testfun(char * const) 这样呢? 参数类型为什么是char * const,若参数类型是被const修饰的,那为什么可以就该str指向的空间的值呢?[/quote] 谁写的导入?[/quote] 导出导入都是我写的
GQB1226 2014-04-24
  • 打赏
  • 举报
回复
受教了,学习~
mujiok2003 2014-04-24
  • 打赏
  • 举报
回复
引用 6 楼 PDD123 的回复:
[quote=引用 3 楼 mujiok2003 的回复:]
void arrayTest(char str[])
其实是

void arrayTest(char *str)
, 不要被它的外表欺骗了。
本来我也觉得是这样,但是我写了DLL然后导入,然后反编译看了看导入函数的名字,结果发现很奇怪:
//.h
_declspec(dllexport)  void testfun(char str[]);
//.cpp
void testfun(char str[])
{
	str[0]=1;
	return;
}
导入函数为什么是 extrn __declspec(dllimport) void __cdecl testfun(char * const) 这样呢? 参数类型为什么是char * const,若参数类型是被const修饰的,那为什么可以就该str指向的空间的值呢?[/quote] 谁写的导入?
PDD123 2014-04-24
  • 打赏
  • 举报
回复
引用 3 楼 mujiok2003 的回复:
void arrayTest(char str[])
其实是

void arrayTest(char *str)
, 不要被它的外表欺骗了。
本来我也觉得是这样,但是我写了DLL然后导入,然后反编译看了看导入函数的名字,结果发现很奇怪:
//.h
_declspec(dllexport)  void testfun(char str[]);
//.cpp
void testfun(char str[])
{
	str[0]=1;
	return;
}
导入函数为什么是 extrn __declspec(dllimport) void __cdecl testfun(char * const) 这样呢? 参数类型为什么是char * const,若参数类型是被const修饰的,那为什么可以就该str指向的空间的值呢?
加载更多回复(5)

65,209

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧