数组名与指针,该怎么处理

数组名与指针
#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可++,说明不再受“指针常量的约束”
最后输出了整个字符串,又说明,其值就是这个数组的内容

感觉彻底混乱了,有没有人解释一下

------解决方案--------------------
void arrayTest(char str[])

其实是

void arrayTest(char *str)

不要被它的外表欺骗了。 
------解决方案--------------------
引用:
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指向的空间的值呢?
------解决方案--------------------
代码: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也可以执行自增运算
------解决方案--------------------
乍看起来c++的cin、cout在输入、输出上比c的scanf、printf简单,不用格式控制符!
但是不用格式控制符,输入输出恰好是你期望的格式的时候好说;等到输入输出不是你期望的格式的时候,你就会觉得还是用格式控制符更方便、更靠谱。
摒弃cin、cout!
使用scanf、printf。

------解决方案--------------------
楼主可以试试这段代码:

#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的原始类型到底是什么。