数组的地址为什么和&数组不一样了? Shepard-Wang

问题是这样的,今天在我想输出一个字符数组的地址时:

char* buffer = new char[256];
cout << "&buffer = " << (void*)buffer << " " <<&buffer << endl;

我本想用 &buffer 来打印 buffer 的地址(因为如果写 buffer 的话会输出字符串的内容)。由于书上是将 buffer 先强转为 void* 再进行打印,我也试了试这个办法,竟然发现两次打印的结果不同!

我当时就有点迷惑,因为我记得 C 语言中对数组取地址和数组的地址是相同的。下面,就让我们来一探究竟。

(ps:其实这个问题很简单,如果你懂的话,可以不浪费你的时间了)

在学习 C 语言的时候,我们都知道数组也是可以取地址的:

extern "C" void test3()
{
	int array[10] = { 0 };

	printf("&array = %p", &array);
}

(extern "C" 会指示编译器编译这部分代码以 C 语言的形式进行编译,如果你使用 .c文件写的,可以忽略这部分)

而且我们会发现,以 %p 的格式来打印array&array 的值是相同的:

printf("array = %p, &array = %p", array, &array);

那么这两个地址有什么区别呢?

typeid().name() 函数我们可以查看变量的类型:

printf("array: %s\n", typeid(array).name());
printf("&array: %s\n", typeid(&array).name());

// 输出:
array: int [10]
&array: int (*)[10]

所以这两个地址的区别就在于类型。array 是数组首元素的地址,而 &array 是整个数组的地址。

指针的一个重要的性质就是 指针的类型决定了指针 ++/-- 操作时的步长 。比如,char* 类型的指针的步长就是 1 个字节,而 int* 类型的指针的步长就是 4 个字节(32 位机器)。

在本例中:

printf("array = %p, &array = %p\n", array, &array);
printf("array + 1 = %p, &array + 1 = %p\n", array + 1, &array + 1);
// 打印:
array = 012FFD08, &array = 012FFD08
array + 1 = 012FFD0C, &array + 1 = 012FFD30

array 的步长是 4 个字节(int 的大小);而 &array 的步长是 40 个字节 int[10] 的大小。

了解了这个之后,回过头来看我们的问题,我们先在 C 语言中模拟一下前面出现的问题:

char* buffer = (char*)malloc(sizeof(char) * 256);

printf("buffer = %p &buffer =  %p\n", buffer, &buffer);
// 打印
buffer = 0120E230 &buffer =  00EFFD1C

区别就在于:**前面在声明数组时,我们使用的格式是:int array[10] 而 后面我们用的是 char* buffer = malloc **

这有什么不同呢?不同之处在于数组真正存在的位置不同:array 存在于栈,而 buffer 存在于堆

观察上面 buffer&buffer 发现,这两个指针的大小差距很大。因此这两个指针一定不在同一个内存区域。

如果你还是不能确定,你可以声明一个在栈上的变量,然后输出一下它的地址:

int a = 10;
printf("&a = %p\n", &a);

// 输出:
buffer = 0132E230 &buffer =  00D6FB84
&a = 00D6FB78

还剩最后一步,如果把 buffer 声明在栈上,是否 buffer 和 &buffer 打印出来的地址就一样呢?

char buffer2[256] = "Hello World";
printf("buffer2 = %p &buffer2 =  %p\n", buffer2, &buffer2);
// 打印:
buffer2 = 00D6FA70 &buffer2 =  00D6FA70

到此为止,这个问题就算是解决了。前面我们讨论了,array&array 的区别;进而探讨了 buffer&buffer 的区别。主要还是本人对指针理解的不够充分,惭愧!

本人能力有限,如果有什么问题,还望大佬指出。