静态数组与动态数组的区别以及二维数组地址详解

静态数组:

在编译期间在栈中分配好内存的数组,在运行期间不能改变存储空间,运行后由系统自动释放。
int a[10];
char b[10];
float c[10];
test a[10]; //test为自定义的类,定义一个包含十个test对象的数组
以上都是静态数组的声明方式。需要注意的是静态数组是在编译期间就已经分配好内存,所以一定要指定数组的大小,不能以变量作为数组的大小
如:
int i;
char a[i]; //这是不允许的,编译期间不能确定i的值,所以无法明确数组的大小,导致编译失败


动态数组:

在程序运行后才分配内存的数组,需要人工手动去创建和释放。
//C语言中利用malloc函数来创建动态数组
int i;
scanf("%d",&i); 
char *p = (char *)malloc(sizeof(char)*i);//分配长度为i的字符数组空间,可以以下标的形式去访问数组。不需要时要调用free()函数手动释放。

//C++中,利用new关键字创建动态数组
int i ;
cin>>i;
char *p = new char[i];//分配长度为i的字符数组空间,可以以下标的形式去访问数组。不需要时要delete p,手动释放。

二维数组地址:

首先要了解
(1)a[i] = *(a+i);
(2)a是数组的首地址也是第一个元素的地址。
(3)a+i代表的是第i个元素的地址。
(4)a+i并不是简简单单第一个元素的地址+i,而应该是第一个元素的地址+i*sizeof(数组类型)。

二维数组可以理解为是一个特殊的一维数组,它的每一个元素也都是一维数组。
                                   
                                  

二维数组a[3][2]可以理解为一个特殊的一维数组,其中每一个元素都是一个一维数组,如a[0][2]实际包含两个元素a[0][0]和a[0][1]。
如图可得到以下结论:
(1)a+i指向a[i][2]:  a为数组a[3][2]的首地址,特殊的一维数组包含3个元素a[0][2],a[1][2],a[2][2]。由一维数组的性质“首地址+i”得到的是第i个元素的地址,所以a+i指向特殊一维数组的第i个元素。
(2)a[i]指向a[i][0]:  特殊的一维数组的每个元素又都是一个数组,如a[0][2]实际包含两个元素a[0][0]和a[0][1]。a[0]相当于一维数组名,指向首元素 a[0][0],所以a[i]指向a[i][0],a[i]+j指向a[i][j]。

从图中看似a+i和a[i]指向的都是a[i][0],其实不然。a+i指向的是a[i],因为a[i]=*(a+i),这个比较难理解的。

void main(){
	int a[3][2]={1,2,3,4,5,6};
	cout<<*a[1]<<endl;
	cout<<*(a+1)<<endl;
}
运行结果

a[i]的确指向的是a[i][0],但a+1取值后仍然是一个地址指向a[i][0]。

可以这样理解,a+i指向的是特殊一维数组的第i个元素,第i个元素还是一个一维数组。*(a+i)直面的意思是想取出第i个元素的内容,但a+i所指空间还是个数组,难道*(a+i)直接就能将整个数组取出来?要知道数组都是通过下标一个个进行访问的,不能整体获得。所以*(a+i)只是获得这个数组空间首元素的地址,这样就可以通过下标对内容进行访问。

最后总结一下:

对于二维数组a[3][2],若看成3行2列的形式。

(1)a+i指向第i行,此时还没有获得第i行元素首地址,没有办法访问其中的元素

(2)*(a+i)或a[i]指向第i行首元素,获得第i行元素的首地址。

(3)a[i]+j指向第i行第j个元素,可以通过a[i]第i行元素的首地址访问各个元素。关键是要记住a[i]=*(a+i),

a[i][j]=*(*(a+i)+j)。



动态二维数组的创建:

C++中:
void main(){
	int row,col;
	cin>>row>>col; //自定义行数和列数
	int **a = new int*[row];  //分配指向行的指针数组,因为(*行指针)才能得到每行首元素的地址,所以可以理解为行指针是指向首元素指针的指针
	for(int k=0; k<row; k++){
		a[k] = new int[col]; //分配行指针所指向的数组
	}

	for(k=0; k<row; k++){ 
		delete [] a[k]; //释放所有行空间
	}
	delete [] a; //释放行指针数组
}

C中:
void main(){
	int row,col;
	scanf("%d,%d",&row,&col); //自定义行数和列数
	int **a = (int**)malloc(sizeof(int *) * row);  //分配指向行的指针数组
	for(int k=0; k<row; k++){
		a[k] = (int *)malloc(sizeof(int) *col); //分配行指针所指向的数组
	}

	for(k=0; k<row; k++){ 
		free(a[k]); //释放所有行空间
	}
	free(a); //释放行指针数组
}


  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
里面都是我新手时期学C的时候整理的一些TXT文档,因为分不够了,所以放上来赚点积分,都是很基础的东西,里面的代码都是经过我测试的,保证可用。 (1)输出Hello,world (2)标识符 (3)常量与变量 (4)整型数据 (5)实型数据 (6)复合赋值表达式 (7)自加自减运算符和逗号表达式 (8)顺序结构及数据输出 (9)数据输入 (10)作业练习一 (11)关系运算符和逻辑运算符 (12)选择结构及条件表达式 (13)循环结构,while语句 (14)循环结构,do while语句 (15)循环结构,for语句 (16)字符型数据 (17)字符型数据实例,作业练习二 (18)函数定义 (19)函数应用实例,作业练习三 (20)指针的定义 (21)函数之间地址值的传递 (22)函数返回地址值 (23)一维数组的定义 (24)一维数组应用实例 (25)一维数组应用实例(2) (26)一维数组应用实例(3) (27)二维数组的定义 (28)二维数组的初始化 (29)二维数组与指针 (30)二维数组应用实例 (31)二维数组应用实例(2) (32)用一维数组来存储字符串 (33)字符串的输入与输出 (34)字符串数组 (35)用于字符串处理的函数 (36)字符串应用实例 (37)传给Main函数的参数 (38)函数指针 (39)函数的递归调用 (40)变量作用域和存储类别 (41)编译预处理和不带参数的宏替换 (42)带参数的宏替换和文件包含 (43)动态存储分配 (44)结构体变量的定义与引用 (45)利用结构体变量构成静态链表 (46)利用结构体变量构成动态链表 (47)共用体的定义与应用 (48)位运算符 (49)File文件的数据输出操作 (50)File文件的数据输入操作 (51)判断文件结束函数 (52)fscanf和fprintf函数 (53)fgets和fputs函数 (54)fread和fwrite函数 (55)文件定位函数 c switch的用法 c 避免调试窗口闪退 c 弹出消息窗口 c 等待函数(sleep) c 定义类成员 c 动态分配内存法定义数组 c 返回二维数组 c 方向键键码 c 改变字体颜色 c 绘制图形 c 获得鼠标当前位置坐标 c 检测键盘按键 c 检测鼠标按下事件 c 将整数转换成二进制数并存放到数组中 c 结构体问题 c 使用winsock实现server和client(通讯程序) c 随机数发生器 c 图形模式详解 c 网页爬虫 c 写图形界面 c 遗传算法实例 c 在图形界面输出文字 c# List的用法 VS2010如何解决每次编译都要重新生成

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值