曲径通幽论坛

标题: 数组的地址 [打印本页]

作者: beyes    时间: 2013-10-1 20:59
标题: 数组的地址
数组名被解释为第一个元素的地址,而在数组名前应用地址运算符时,得到的是整个数组的地址:
  1. int add[10];
  2. cout << add << endl;
  3. cout << &add << endl;
复制代码
这两个输出的值一样,即两个地址相同。但概念上,这两者却不一样。add 或 &add[0] 是一个 4 字节整型内存地址,而 &add 却是一个 40 字节的内存地址块的地址。

因此,add + 1 是将地址加上 4 ,而 &add + 2 则表示的是将地址加上 80 。换句话来说,add 是一个 int 指针 ( *int ) ,而 &add 则是一个指向包含 10 个元素的 int 数组 ( int(*)[10] ) 。

可以像下面这样声明和初始化这种指针:
  1. int (*pas) [10] = &add;
复制代码
上面 pas 指向的是一个包含了 10 个 int 原型的数组。

需要注意的是,不能省掉括号,即不能写成 int *pas[10] = &add; 。这是因为,[ ] 的优先级比 * 高,这样 pas 就会先于 [10] 结合,从而导致了 pas 变成了一个 int 指针数组,且包含了 10 个这样的指针,所以括号必不可少。

如果要描述变量的类型,可将声明中的变量名删除,因此 pas 的类型为 int (*) [20] 。

由于 pas 被设置为 &add,所以 *pas 和 add 是等价的,所以 (*pas)[0] 就是 add 数组的第一个元素。

将上面所述,用下面一段简单的代码测试,比较其地址关系便可一目了然:
[C++] 纯文本查看 复制代码
#include <iostream>
using namespace std;

int main()
{

        int add[10];

        cout << add << endl;

        cout << &add + 2 << endl;

        int (*pas) [10] = &add;

        cout << pas+1 << endl;

        cout << pas+2 << endl;

        add[0] = 88;

        cout << "--------------------" << endl;

        cout << pas << endl;

        cout << *pas << endl;
        cout << **pas << endl;

        cout << (*pas)[0] << endl;

        return 0;
}


运行输出:
[beyes@groad ~]$ ./address
0xbfc0c434
0xbfc0c484
0xbfc0c45c
0xbfc0c484
--------------------
0xbfc0c434
0xbfc0c434
88
88


另外,还有一种情况,如果上面的 add 数组是 char 类型,那么如何输出其地址:
[C++] 纯文本查看 复制代码
#include <iostream>

using namespace std;

int main()
{
        char add[10];

        cout << add << endl;

        return 0;
}


这样输出是乱码,而不会是 add 的地址当一个数组是 char 类型时,cout 其数组名时,会优先输出其数组的内容,这里数组名相当于一个字符串指针。那么要想输出数组地址,可以像上面在 add 面前使用地址运算符,即 &add 。还可以在数组名面前使用 (void *) 进行地址的强制声明,这样就可以输出数组地址了。再比较下面的程序:
[C++] 纯文本查看 复制代码
#include <iostream>

using namespace std;

int main()
{
        char add[10];
        cout << add << endl;

        add[0] = 'a';
        add[1] = 'b';
        add[2] = 'c';

        cout << &add[2] << endl;

        return 0;
}


在第 2 条 cout 语句中,你同样不会获得 add[2] 这个元素的地址,而仍然是乱码,因为它仍然将该地址当作是从该元素为起始的字符串指针,而该数组里又没有 '\0' 结尾的元素,因此仍然输出乱码。同样,想获得 add[2] 的地址,可以在 &add[2] 的前面加上 (void *) 进行强制转换,即写成 (void *)&add[2];





欢迎光临 曲径通幽论坛 (http://www.groad.net/bbs/) Powered by Discuz! X3.2