问题
#include <iostream>
using namespace std;
int main()
{
int * a[] = {
//空白处
};
*a[2] = 123;
a[3][5] = 456;
if(! a[0] ) {
cout << * a[2] << "," << a[3][5];
}
return 0;
}
要求在空白处填写代码,使得输出的结果为:123,456
咋一看真的感觉很莫名其妙,觉得无从下手,我也是分析了好久才想通了这道问题。
这道题可谓是指针中的变态,既要有深厚的指针概念的理解,也要对c++的new关键字掌握。
问题剖析
首先我们都知道数组这个概念。比如int a;是一个整数变量,这条语句执行计算机会在内存中分配一个int 类型大小(4个字节)的空间。如果是int a[3],就是定义一组int 类型的数据,计算机会分配4个int 类型大小的空间。
如下所示:
int a
a |
---|
整数数据 |
int a[3]
a[0] | a[1] | a[3] |
---|---|---|
数据1 | 数据2 | 数据3 |
再想想,如果是int a[]这种的呢?那么这种计算机在初始化时会根据你大括号中的数据个数分配多少个空间。比如int a[]={1,2}就是:
a[0] | a[1] |
---|---|
数据1 | 数据2 |
既然上面可以分配多个int类型大小的空间,那我们为什么不能分配多少个int * 指针类型大小的空间呢?
如 int * a[2]就是分配了2个int *类型大小的空间。也就是说这个a也是一个数组,但它里面存放的类型不是int类型了,而是int * 类型。如下
int *a[0] | int *a[1] |
---|---|
指针1 | 指针2 |
那么我们就分析出来这个 int * a[]也就是一个指针数组,只不过我们没有指定它的长度,需要我们在后面的大括号中初始化,写入几个指针就有几个指针的长度。
也就是说对于上面的问题我们在大括号中要填入int 指针类型的值.
接着来看底下这几个赋值:
*a[2] = 123;
a[3][5] = 456;
*a[2]这是啥意思啊?我们来拆解一下,首先我们知道a是一组Int 类型的数组,那数组里面存放的也就是指针类型的变量,a[2]就是说在数组的第三个元素,也就是第三个指针元素。所以a[2]是一个int 类型的指针,那么在指针前面加一个号是不是就是对这个指针指向的地址取值啊!
好!这个我们分析出来,先放在这儿!
再来看看a[3][5],同样拆开来分析。a[3]是不是就是这个数组中第四个指针变量啊,那么对这个指针变量再来一个[5]是不是就是对a[3]指向的那块连续的地址再来一个通过下标取值的操作啊!所以a[3]指针指向的是一块int 数组。
最后再来判断 : !a[0] 就是判断a数组第一个指针元素是否为空呗!
所以我们在空白处应该这样填写:
#include <iostream>
using namespace std;
int main()
{
int * a[] = {
0,//!a[0]为真
0,//为NULL也行
new int ,//new分配一个int 类型的空间,并返回对应的地址
new int [6]//分配一块int 数组,长度为6,只要大于等于6就行
};
*a[2] = 123;
a[3][5] = 456;
if(! a[0] ) {
cout << * a[2] << "," << a[3][5];
}
return 0;
}
延伸想法
- 其实在c语言中我们为什么不用malloc()函数来分配来代替new关键字呢?
经过测试下面这段c代码的效果是等价的
#include <stdio.h>
#include <stdlib.h>
int main(void){
int *p1=(int *)malloc(sizeof(int));
int *p2=(int *)malloc(sizeof(int)*6);
int * a[] = {
0,//!a[0]为真
0,//为NULL也行
p1,
p2
};
*a[2] = 123;
a[3][5] = 456;
if(! a[0] ) {
printf("%d,%d",*a[2],a[3][5]);
}
return 0;
}
2.如何考虑 char a[n][]和char *a[]分配的内存空间?
假设char a[3][]