zoukankan      html  css  js  c++  java
  • 别人不会给你说的---C语言中数组名和指针的区别 及 sizeof用法

    引自:

    http://blog.csdn.net/tianyue168/article/details/5781924

    1. #i nclude <iostream.h>   
    2. int  main( int  argc,  char * argv[])   
    3. {   
    4. char  str[10];   
    5.   char  *pStr = str;   
    6.  cout <<  sizeof (str) << endl;   
    7.  cout <<  sizeof (pStr) << endl;   
    8.   return  0;   

     实际情况是:第6行输出10,第7行输出4;

    先给出三个结论:

      (1)数组名的内涵在于其指代实体是一种数据结构,这种数据结构就是数组;

      (2)数组名的外延在于其可以转换为指向其指代实体的指针,而且是一个指针常量;

      (3)指向数组的指针则是另外一种变量类型(在WIN32平台下,长度为4),仅仅意味着数组的存放地址!

    1、数组名指代一种数据结构:数组

      现在可以解释为什么第1个程序第6行的输出为10的问题,根据结论1,数组名str的内涵为一种数据结构,即一个长度为10的char型数组,所以sizeof(str)的结果为这个数据结构占据的内存大小:10字节。

    1. int  intArray[10];   
    2. cout <<  sizeof (intArray) ;

    第2行的输出结果为40(整型数组占据的内存空间大小)。

    2、数组名可作为指针常量

      根据结论2,数组名可以转换为指向其指代实体的指针,所以程序1中的第5行数组名直接赋值给指针,程序2第7行直接将数组名作为指针形参都可成立。

    下面的程序成立吗?

    C++代码
    1. int  intArray[10];   
    2. intArray++;

    读者可以编译之,发现编译出错。原因在于,虽然数组名可以转换为指向其指代实体的指针,但是它只能被看作一个指针常量,不能被修改。

    而指针,不管是指向结构体、数组还是基本数据类型的指针,都不包含原始数据结构的内涵,在WIN32平台下,sizeof操作的结果都是4。
    顺便纠正一下许多程序员的另一个误解。许多程序员以为sizeof是一个函数,而实际上,它是一个操作符,不过其使用方式看起来的确太像一个函数了。语句 sizeof(int)就可以说明sizeof的确不是一个函数,因为函数接纳形参(一个变量),世界上没有一个C/C++函数接纳一个数据类型(如 int)为"形参"。

    3、数据名可能失去其数据结构内涵

    到这里似乎数组名魔幻问题已经宣告圆满解决,但是平静的湖面上却再次掀起波浪。请看下面一段程序:

    C++代码
    1. #i nclude <iostream.h>   
    2. void  arrayTest( char  str[])   
    3. {   
    4.  cout <<  sizeof (str) << endl;   
    5. }   
    6. int  main( int  argc,  char * argv[])   
    7. {   
    8.   char  str1[10] =  "I Love U" ;   
    9.  arrayTest(str1);   
    10.   return  0;   
    11. }  
      程序的输出结果为4。不可能吧? 


      一个可怕的数字,前面已经提到其为指针的长度!

      结论1指出,数据名内涵为数组这种数据结构,在arrayTest函数体内,str是数组名,那为什么sizeof的结果却是指针的长度?这是因为:

      (1)数组名作为函数形参时,在函数体内,其失去了本身的内涵,仅仅只是一个指针;

      (2)很遗憾,在失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等操作,可以被修改。

      所以,数据名作为函数形参时,其全面沦落为一个普通指针!它的贵族身份被剥夺,成了一个地地道道的只拥有4个字节的平民。

    一、sizeof的概念 

      sizeof是C语言的一种单目操作符,如C语言的其他操作符++、--等。它并不是函数。sizeof操作符以字节形式给出了其操作数的存储大小。操作数可以是一个表达式或括在括号内的类型名。操作数的存储大小由操作数的类型决定。

    二、sizeof的使用方法 
      1、用于数据类型 
    sizeof使用形式:sizeof(type) 
    数据类型必须用括号括住 。如sizeof(int)。 
    2、用于变量 
    sizeof使用形式:sizeof(var_name)或sizeof var_name  
    变量名可以不用括号括住。如sizeof (var_name),sizeof var_name等都是正确形式。带括号的用法更普遍,大多数程序员采用这种形式。 
     
    三。sizeof用法总结
    在VC中,sizeof有着许多的用法,而且很容易引起一些错误。下面根据sizeof后面的参数对sizeof的用法做个总结。
    A. 参数为数据类型或者为一般变量。例如sizeof(int),sizeof(long)等等。这种情况要注意的是不同系统系统或者不同编译器得到的结果可能是不同的 。例如int类型在16位系统中占2个字节,在32位系统中占4个字节。
    B. 参数为数组或指针。下面举例说明.
    int a[50]; //sizeof(a)=4*50=200; 求数组所占的空间大小
    #int* a= “hello world”,应该是12(要注意)
    int *a=new int[50];// sizeof(a)=4; a为一个指针,sizeof(a)是求指针
    //的大小,在32位系统中,当然是占4个字节。
    C. 参数为结构或类。Sizeof应用在类和结构的处理情况是相同的。但有两点需要注意,第一、结构或者类中的静态成员不对结构或者类的大小产生影响,因为静态变量的存储位置与结构或者类的实例地址无关
    第二、没有成员变量的结构或类的大小为1,因为必须保证结构或类的每一 个实例在内存中都有唯一的地址。
    下面举例说明,
    Class Test{int a;static double c};//sizeof(Test)=4.
    Test *s;//sizeof(s)=4,s为一个指针。
    Class test1{ };//sizeof(test1)=1;
    D. 参数为其他。下面举例说明。
    int func(char s[5]);
    {
    cout<<sizeof(s)<<endl;
    //数的参数在传递的时候系统处理为一个指针,所
    //以sizeof(s)实际上为求指针的大小。
    return 1;
    }
    sizeof(func(“1234”))=4//因为func的返回类型为int,所以相当于
    //求sizeof(int). 还要注意的是“1234”而不是“12345”)
    以上为sizeof的基本用法,在实际的使用中要注意分析VC的分配变量的分配策略,这样的话可以避免一些错误。
     
     
    示例
    char str[20]="0123456789"; int a=strlen(str); //a=10; >>>> strlen 计算字符串的长度,以结束符 0x00 为字符串结束。
    int b=sizeof(str); //而b=20; >>>> sizeof 计算的则是分配的数组 str[20] 所占的内存空间的大小,不受里面存储的内容改变。
     
    上面是对静态数组处理的结果,如果是对指针,结果就不一样了
    char* ss = "0123456789";
    sizeof(ss) 结果 4 ===》ss是指向字符串常量的字符指针,sizeof 获得的是一个指针的之所占的空间,
    应该是长整型的,所以是4
     
    sizeof(*ss) 结果 1 ===》*ss是第一个字符 其实就是获得了字符串的第一位'0' 所占的内存空间,
    是char类型的,占了 1 位 
     
     
    #include <iostream>
    using namespace std;
    
    int main() {
        // your code goes here
        
        int *p=new int[10];
        cout<<sizeof(p)<<endl;
        int a[10];
        cout<<sizeof(a)<<endl;
        
        int *q=(int*)malloc(sizeof(int)*10);
        cout<<sizeof(q)<<endl;
        
        char* c="abcdef";
        cout<<sizeof(c)<<endl;
        cout<<sizeof(*c)<<endl;
        //cout<<strlen(c)<<endl;
    //    strlen(tt)就是求 tt指向的字符串的长度
    //sizeof(tt) 才是求tt的大小
        return 0;
    }
    // sizeof 和strlen 的区别 及在指针与数组中的不同结果
    
    char *p = "123456789";
    
    cout << "sizeof(p) = " << sizeof(p) << endl; // sizeof(p) = 4 指针的位数
    
    cout << "strlen(p) = " << strlen(p) << endl; // strlen(p) = 10
    
    char str[] = "123456789";
    
    cout << "sizeof(str) = " << sizeof(str) << endl;//sizeof(str) = 11 加上一个''
    
    cout << "strlen(str) = " << strlen(str) << endl;//strlen(str) = 10
    
    //指针与数组的差别
    
    // p[1] = '8'; error, 指针的值不能改变,指针指向的值是const的
    
    str[5] = '9'; // right, 数组的值可以改变
    
    // void *p;
    
    void *void_p = malloc(100);
    
    cout << "sizeof(void_p) = " << sizeof(void_p) << endl; //sizeof(void_p) = 4, 指针的位数
    
    char *char_p = NULL;
    
    cout << sizeof(*char_p) << endl; // sizeof(*char_p) = 1;
  • 相关阅读:
    POJ 1330 Nearest Common Ancestors(LCA Tarjan算法)
    LCA 最近公共祖先 (模板)
    线段树,最大值查询位置
    带权并查集
    转负二进制
    UVA 11437 Triangle Fun
    UVA 11488 Hyper Prefix Sets (字典树)
    UVALive 3295 Counting Triangles
    POJ 2752 Seek the Name, Seek the Fame (KMP)
    UVA 11584 Partitioning by Palindromes (字符串区间dp)
  • 原文地址:https://www.cnblogs.com/fickleness/p/3341919.html
Copyright © 2011-2022 走看看