zoukankan      html  css  js  c++  java
  • 数组首地址与数组名取地址的区别

    C语言数组首地址和数组名取地址区别


    原文地址:http://hi.baidu.com/surfmygod/blog/item/53d44914cdb8a5d6a7ef3f13.html

     

    本文适用于机器为32位,编译器为VC6.0。

    先来看下面一个例子:
    main()
    {
    int a[5]={0x11121314,0x21222324,0x31323334,0x41424344,0x51525354};
    int *ptr1=(int *)(&a+1);
    int *ptr2=(int *)(a+1);
    printf("%x,%x",ptr1[-1],*ptr2);
    getch();
    }

    你可以试着在软件中编译运行一下,结果是51525354,21222324。你可以试着写以下程序再在计算机中编译运行下:

    main()

    {

    inta[5]={0x11121314,0x21222324,0x31323334,0x41424344,0x51525354};

    printf("%p %p ",a,&a);

    printf("%d %d ",sizeof(a),sizeof(&a));

    printf("%p %p",&a+1,a+1);

    getch();

    }

    你可以看到前两行a和&a打印的结果是一样的(比如0012FF6C),后两行的结果是都是20,而&a+1的结果是0012FF6C,即a的起始地址后移20字节。

    看到这里对于a和&a的区别是不是有些眉目了?

    不错,a和&a的值虽然一样,但是前者表示的是数组a的首地址,进阶为数组元素长度,而后者也是表示数组a的首地址

    (或许有些人不同意我这个观点,对地址取地址应该是指向指针的指针呀。

    不过你注意了没有,a和&a值是一样的,试想如果这里表示的是指向指针的指针,那么a的地址和指向a的指针的地址可能一样么?

    两个指针都指向数组首地址,怎么会是指向指针的指针?

    还有一点需要强调,对一个指针进行sizeof运算,32位系统下应该得到4,而对数组名进行sizeof运算得到的结果却是20,这说明了什么?

    很显然,数组名虽然能够拿出来代表一个地址,但是它和指针还是有区别的,对它进行sizeof运算也不会得到指针的大小。

    不信?你可以试试sizeof(&a[0])和sizeof(a),看看结果是不是相同),但是是将整个数组作为一个对象来看待的,进阶为整个数组长度。

    也就是说,a和&a虽然值相同,但是a是将所有数组元素看成一个个不同的个体来对待的,而&a是将整个数组作为一个整体来对待的。

    这里要强调的是,a+1和&a[1]其实是一样的,都是代表a数组向后偏移一个元素的地址,你可以再用sizeof关键字打印一下两个的值。

    但是a和&a[0]的意义相同么?若打印地址的话,两者确实是一样的,但是你也用sizeof打印下两者,一样么?再试试a+0呢?

    很显然,a和a+0是有区别的,但是a+0和&a[0]是含义相同的。

    所以,你可以说a+i和&a[i]含义相同,但是绝不能说a和&a[0]或a+0含义相同。所以&a+1后移20位为&a+sizeof(&a),而a+1却是a+sizeof(a[i])。

    (《C语言深度解剖》认为在32为系统下sizeof(&a)的值仍为4,我觉得是不对的。

    他觉得是VC6.0错了,其实不止VC,其他很多编译器得到的结果也不会是4,这说明a和&a在C中本来就不是作为指针来用的,只是具有指针的部分性质而已。)

    ptr1是将&a+1强转为int类型指针,此时打印ptr1[-1]即将ptr指针前移sizeof(int)个字节,故打印结果是5。

    这样一来后面的也明了了,a+1的值为在数组a的首地址上后移sizeof(int)个字节,

    然后强转为int类型指针(其实强转并没有改变什么,原来类型即为整型指针,可以去掉强转),最后输出结果为21222324。

     

    再想一下,如果将第一例第五行改为int *ptr2=(int *)((int)a+1);打印结果会是什么?
    这里要考虑数据在计算机中的存储模式:大端模式和小端模式。解释一下:
    大端模式(Big_endian):字数据的高字节存储在低地址中,而字数据的低字节则存放在高地址中。
    小端模式(Little_endian):字数据的高字节存储在高地址中,而字数据的低字节则存放在低地址中。
    在大端模式下,a在计算机中存储如下(从低地址到高地址,一个十六进制数代表内存的一个字节,下同):
    0x11 0x12 0x13 0x14 0x21 0x22 0x23 0x24 0x31 0x32 0x33 0x34 0x41 0x42 0x43 0x440x51 0x52 0x53 0x54
    在小端模式下,a在计算机中存储如下:
    0x14 0x13 0x12 0x11 0x24 0x23 0x22 0x21 0x34 0x33 0x32 0x31 0x44 0x43 0x42 0x410x54 0x53 0x52 0x51
    (int)a表示将a的首地址强转为整型数据(若原来是0012FF6C,转换后仍为0012FF6C,但是这时已经不是表示地址而是一个十六进制整型数了),

    这时+1代表整型数(int)a加1(变为0012FF6D),再把结果强转为整形指针,故指向的数据地址为0012FF6D,即上述存储去的第二个字节开始处。

    此时输出*ptr2,即输出a数组存储区中第二到第五字节组成的一个整型数,若为大端模式则输出12131421,若为小端模式则输出24111213。


  • 相关阅读:
    maptalks 开发GIS地图(16)maptalks.three.09
    maptalks 开发GIS地图(15)maptalks.three.08
    maptalks 开发GIS地图(14)maptalks.three.07
    maptalks 开发GIS地图(12)maptalks.three.05 bar-music
    Use mongoose-CRUD operations
    First Mongoose Model
    MongoDB-1-CRUD Operations
    Mongo DB-0
    Kill port process
    Defining RESTful Routes(CRUD operations)
  • 原文地址:https://www.cnblogs.com/melons/p/5791863.html
Copyright © 2011-2022 走看看