这段代码运行结果为4,4,16,4。
      问(1)为什么pArray_No1初始化为指向10个int型的内存地址块(我的理解没错吧?)
            而sizeof的运算结果只是1个int型的字节大小,按理来说应该是10个啊,为什么呢?
      问(2)pArray_No2=a;说明pArray_No2指向了数组a首元素的地址,sizeof(pArray_No2)
            =4,我理解为编译器只计算了数组a首元素地址的内存空间大小;但是问题出来了,a
代表的肯定是数组a首元素的地址,但是这里sizeof(a)=16,说明编译器计算的不是                     
一个首元素,而是整个数组4个元素的地址占的内存空间。我迷惑了,pArray_No2与
a代表的意义相同,但是为什么sizeof的结果却截然不同呢?
       int *pArray_No1,*pArray_No2,a[]={1,2,3,4};
pArray_No1=new int[10];
pArray_No2=a;
       cout<<sizeof(pArray_No1)<<endl        //结果为4
    <<sizeof(pArray_No2)<<endl      //结果为4
    <<sizeof(a)<<endl               //结果为16
    <<sizeof(&a[0])<<endl;          //结果为4
delete [] pArray_No1;过后我对问题(2)有些自己的理解,不知道是否正确:“pArray_No2指向了数组a首元素的地址”
这个没错,所以pArray_No2储存的就是数组a首元素的地址值,sizeof(pArray_No2)=4那是没错的;
而“a代表的肯定是数组a首元素的地址”这句也没错,但是这里a是数组,数组虽然也算指针,而数组
与指针是有区别的,所以sizeof(a)=16就没错了。然而我的理解只是知其然而不知其所以然,为什么
“数组与指针是有区别的”呢?望爱专细节的朋友帮忙解惑,在下万分感谢!有时候被些问题搞得“食
之无味,夜不能寐”,还好有csdn这个平台,有这么多的好心人帮忙!

解决方案 »

  1.   

      cout < <sizeof(pArray_No1) < <endl        //结果为4  指针一般占4个字节
        < <sizeof(pArray_No2) < <endl      //结果为4       同上
        < <sizeof(a) < <endl              //结果为16     a是个含4个整型的数组,所以4X4=16
        < <sizeof(&a[0]) < <endl;          //结果为4     &a[0]是个地址,相当于指针,所以也是4
      

  2.   

    谢谢kondykuang的回答!但是还请你说具体点,我还是不只其所以然!
      

  3.   

    a代表的肯定是数组a首元素的地址,这个没问题.
    但a的类型为 int* [4],所以大小为4*4 = 16
      

  4.   

    这个说的比较清楚了。
    我这边有篇文章推荐你看下
    http://www.vcfans.com/2008/09/c-c-array-of-indicators-and-to-explore-the-deep-differences-between.html
    一看我想你就明白了
      

  5.   


    7.3 指针与数组的对比
    C++/C 程序中,指针和数组在不少地方可以相互替换着用,让人产生一种错觉,以
    为两者是等价的。
    数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。数组名对应着(而
    不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变。
    指针可以随时指向任意类型的内存块,它的特征是“可变”,所以我们常用指针来操
    作动态内存。指针远比数组灵活,但也更危险。
    高质量C++/C 编程指南,v 1.0
    2001 Page 46 of 101
    下面以字符串为例比较指针与数组的特性。
    7.3.1 修改内容
    示例7-3-1 中,字符数组a 的容量是6 个字符,其内容为hello\0。a 的内容可以改变,
    如a[0]= ‘X’。指针p 指向常量字符串“world”(位于静态存储区,内容为world\0),常
    量字符串的内容是不可以被修改的。从语法上看,编译器并不觉得语句p[0]= ‘X’有什么
    不妥,但是该语句企图修改常量字符串的内容而导致运行错误。
    char a[] = “hello”;
    a[0] = ‘X’;
    cout << a << endl;
    char *p = “world”; // 注意p 指向常量字符串
    p[0] = ‘X’; // 编译器不能发现该错误
    cout << p << endl;
    示例7-3-1 修改数组和指针的内容
    7.3.2 内容复制与比较
    不能对数组名进行直接复制与比较。示例7-3-2 中,若想把数组a 的内容复制给数
    组b,不能用语句 b = a ,否则将产生编译错误。应该用标准库函数strcpy 进行复制。
    同理,比较b 和a 的内容是否相同,不能用if(b==a) 来判断,应该用标准库函数strcmp
    进行比较。
    语句p = a 并不能把a 的内容复制指针p,而是把a 的地址赋给了p。要想复制a
    的内容,可以先用库函数malloc 为p 申请一块容量为strlen(a)+1 个字符的内存,再用
    strcpy 进行字符串复制。同理,语句if(p==a) 比较的不是内容而是地址,应该用库函
    数strcmp 来比较。
    // 数组…
    char a[] = "hello";
    char b[10];
    strcpy(b, a); // 不能用 b = a;
    if(strcmp(b, a) == 0) // 不能用 if (b == a)

    // 指针…
    int len = strlen(a);
    char *p = (char *)malloc(sizeof(char)*(len+1));
    strcpy(p,a); // 不要用 p = a;
    if(strcmp(p, a) == 0) // 不要用 if (p == a)

    示例7-3-2 数组和指针的内容复制与比较
    高质量C++/C 编程指南,v 1.0
    2001 Page 47 of 101
    7.3.3 计算内存容量
    用运算符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) 数组退化为指针
    7.4 指针参数是如何传递内存的?
    如果函数的参数是一个指针,不要指望用该指针去申请动态内存。示例7-4-1 中,
    Test 函数的语句GetMemory(str, 200)并没有使str 获得期望的内存,str 依旧是NULL,
    为什么?
    void GetMemory(char *p, int num)
    {
    p = (char *)malloc(sizeof(char) * num);
    }
    void Test(void)
    {
    char *str = NULL;
    GetMemory(str, 100); // str 仍然为 NULL
    strcpy(str, "hello"); // 运行错误
    }
    示例7-4-1 试图用指针参数申请动态内存
    高质量C++/C 编程指南,v 1.0
    2001 Page 48 of 101
    毛病出在函数GetMemory 中。编译器总是要为函数的每个参数制作临时副本,指针
    参数p 的副本是 _p,编译器使 _p = p。如果函数体内的程序修改了_p 的内容,就导致
    参数p 的内容作相应的修改。这就是指针可以用作输出参数的原因。在本例中,_p 申请
    了新的内存,只是把_p 所指的内存地址改变了,但是p 丝毫未变。所以函数GetMemory
    并不能输出任何东西。事实上,每执行一次GetMemory 就会泄露一块内存,因为没有用
    free 释放内存。
    如果非得要用指针参数去申请内存,那么应该改用“指向指针的指针”,见示例7-4-2。
    void GetMemory2(char **p, int num)
    {
    *p = (char *)malloc(sizeof(char) * num);
    }
    void Test2(void)
    {
    char *str = NULL;
    GetMemory2(&str, 100); // 注意参数是 &str,而不是str
    strcpy(str, "hello");
    cout<< str << endl;
    free(str);
    }
    示例7-4-2 用指向指针的指针申请动态内存
    由于“指向指针的指针”这个概念不容易理解,我们可以用函数返回值来传递动态
    内存。这种方法更加简单,见示例7-4-3。
    char *GetMemory3(int num)
    {
    char *p = (char *)malloc(sizeof(char) * num);
    return p;
    }
    void Test3(void)
    {
    char *str = NULL;
    str = GetMemory3(100);
    strcpy(str, "hello");
    cout<< str << endl;
    free(str);
    }
    示例7-4-3 用函数返回值来传递动态内存
    高质量C++/C 编程指南,v 1.0
    2001 Page 49 of 101
    用函数返回值来传递动态内存这种方法虽然好用,但是常常有人把return 语句用错
    了。这里强调不要用return 语句返回指向“栈内存”的指针,因为该内存在函数结束时
    自动消亡,见示例7-4-4。
    char *GetString(void)
    {
    char p[] = "hello world";
    return p; // 编译器将提出警告
    }
    void Test4(void)
    {
    char *str = NULL;
    str = GetString(); // str 的内容是垃圾
    cout<< str << endl;
    }
    示例7-4-4 return 语句返回指向“栈内存”的指针
    用调试器逐步跟踪Test4,发现执行str = GetString 语句后str 不再是NULL 指针,
    但是str 的内容不是“hello world”而是垃圾。
    如果把示例7-4-4 改写成示例7-4-5,会怎么样?
    char *GetString2(void)
    {
    char *p = "hello world";
    return p;
    }
    void Test5(void)
    {
    char *str = NULL;
    str = GetString2();
    cout<< str << endl;
    }
    示例7-4-5 return 语句返回常量字符串
    函数Test5 运行虽然不会出错,但是函数GetString2 的设计概念却是错误的。因为
    GetString2 内的“hello world”是常量字符串,位于静态存储区,它在程序生命期内
    恒定不变。无论什么时候调用GetString2,它返回的始终是同一个“只读”的内存块。
      

  6.   

    指针与数组是有区别的。
    . 在动态运行时,指针保存了某内存的地址(不管是数据块内存还是函数入口地址),数组也是,所以它们的行为是一样的;
    . 但在静态编译时,编译器自动为数组标记了其内存块的大小,所以我们可以用sizeof(数组名)取得它的大小。注意在编译时,因为编译器已经知道了sizeof(数组名)的值,所以直接用标记值替换sizeof(数组名),最终效果就是相当于一个常量。一句话,sizeof取得的是数据型的大小(数组是特殊的数据型)。
    那么上面的代码就好解析了:cout <<sizeof(pArray_No1) <<endl        // 数据型为int *,指针
         <<sizeof(pArray_No2) <<endl      // 数据型为int *,指针
         <<sizeof(a) <<endl              // 数据型为int [4],静态数组
         <<sizeof(&a[0]) <<endl          //数据型为int *,指针     // 为方便理解,多加几行
         <<sizeof(a[0]) <<endl          //数据型为int,静态数据类型
         <<sizeof(&pArray_No2) <<endl   //数据型为int**,本质上还是指针
         <<sizeof(int) <<endl;          //数据型为int,静态数据类型
      

  7.   

    再谈谈以数组作为参数的函数。先看代码:
    void FuckRB(char[] szGirlName)
    {
        // ...
        cout<<sizeof(szGirlName);    // 数据型为char[],相当于char*,指针
    }int main()
    {
        char name[] = "WuTengLan's daughter";
        FuckRB(name);
        return 0;
    }
    函数是在运行时动态调用的,所以在FuchRB()内部看来,szGirlName仅仅是一个指针(char *)而已。因为编译器有记录的标识符是name,并不是szGirlName
      

  8.   

    *pArray_No1   这是个指向INT类型的<指针>
    *pArray_No2   这也是个指向INT类型的<指针>
    a[]={1,2,3,4} 这是有4个INT类型元素的数组指针的大小在32机里就是4个Byte, 不管它指向什么类型的变量
    sizeof只是取变量的大小.
    sizeof( pArray_No1 )  变量pArray_No1为指针, 所以它的大小当然是4个Byte
    sizeof( a )  a是个数组, 大小当然为4Byte * 4 = 16Byte
    sizeof( &a[ 0 ] ) 这是取a数组第一个元素的地址, 那当然是个指针了, 就是4个Byte这很好理解的. 
      

  9.   

    关于sizeof的使用,只要是指针,返回值为跟系统位数有关,32位为4,64位为8
    如果是数组,则返回数组的大小,以字节为单位
    例如:
    int *p;
    char *pp;
    double *ppp;
    sizeof(p)=sizeof(pp)=sizeof(ppp)=4;//32位系统
    int p[10];
    char pp[10];
    double pp[10];
    sizeof的结果为 40=10*sizeof(int),10=10*sizeof(char),80=10*sizeof(double)
      

  10.   

    你就把数组当成是一个object,只不过它有一个重载操作符可以转换成元素类型的指针就好理解了。
    譬如int[10],就是一个数组类型的object,size是10*sizeof(int),它有一个强制转换符可以将这个object的指针转换成int*。
    本质上数组和指针压根不是一个东西,此流毒我认为始作俑者是谭浩强。
      

  11.   

    类似的比方:CString可以转换成LPCTSTR,假设CString str = "Hello World";但是你能说sizeof(str)和sizeof(LPCSTR)相同吗?
      

  12.   

    哈哈!codewarrior兄!你又光顾寒舍!你的指导依然是那么一针见血!
      

  13.   

    你这句我赞同!但是请看这句
    pArray_No2=a;
    那么pArray_No2与a的类型应该是一样的,但是sizeof(pArray_No2)=4;sizeof(a)=16;这里为什么又不一致了呢?
    所以你的回答是片面的!还是谢谢了,大家共同进步!
      

  14.   

    最后一句错得都没边没谱了。
    CString就是能当成LPCTSTR用,于是乎种种迹象表明CString就是LPCTSTR!这能说通?
    数组就是数组,指针就是指针,完全两种东西!
    正确的是:数组的名,在某些情况下可以当成指针使用。仅此而已,再往前进一步就变成了谬误。
      

  15.   

    再问你一个,你认为下面两句话话能不能编译通过呢:
    char a[10];
    int b[sizeof(a)];想想看,然后再考虑考虑编译器是否将数组和指针区别对待了?
      

  16.   

       MSDN上的解释为:
    The sizeof keyword gives the amount of storage, in bytes, associated with a
    variable or a type (including aggregate types). 
    This keyword returns a value of type size_t.
    其返回值类型为size_t,在头文件stddef.h中定义。这是一个依赖于编译系统的值,一
    般定义为
    typedef unsigned int size_t;
         sizeof获取的类型的大小,楼主只需要理解编译期和运行期的区别就行了,就是静态的数组的大小在编译期就决定了,所以sizeof获取的是数组的大小,而指针动态开辟内存,sizeof不能获取它的开辟的内存的大小,它只能指针在该编译器的编译期的大小,在win32平台上无论什么指针的大小都是4个指针。
      

  17.   

    sizeof(a)=10
    int b[sizeof(a)]=int b[10]
    我弱弱的感觉应该能编译通过!呵呵!
    codewarrior兄这么爱抓细节,我喜欢!
      

  18.   

    兄弟居然能在代码中加入AV女皇,心中的黄可见一斑!在下也是AV爱好者,但是与大头蜂比起来差得太远!
    言归正传,你的讲解确实很独到,以致我昨天回复的时候放到最后却因为连续回复3次而不能回复了,所以今天补上!codewarrior与你的回答让我很受用,感觉茅塞顿开!
      

  19.   

    其实这和数组和指针关系无关,主要是sizeof理解错了