本文共 3519 字,大约阅读时间需要 11 分钟。
一、数组作为参数/返回值情况是怎样的?内存是怎么变化?
1、回顾学习过的传参情况。 例子1: 传递一个int类型的数据。 void fun(int x) //x = aint a;
fun(a); -> 传递了整个a的值过去。例子2: 传递普通指针过去。
void fun(int *x) // x = pint a;
int *p = &a; fun(p); -> 传递了整个p的值过去。例子3: 传递函数过去。
void fun(void(*p)(int)) // p = my_fun
void my_fun(int a)
fun(my_fun); -> 传递了函数的地址过去。2、传递一个数组,情况会怎么样?
void fun(int *x) //x = A = &A[0] -> 首元素的地址类型:int*, 所以需要使用int*的变量去接住这个地址 void fun(int x[3])//这种写法是正确,但是看起来好想把整个数组都传递过来,实际只是传递了首元素的地址 void fun(int x[]) {}
int main(int argc,char *argv[])
{ int A[3] = {1,2,3}; fun(A); -> 数组名A在这里不是作用于sizeof,所以代表的是首元素的地址 &A[0]等价于 fun(&A[0]);
}结论: 数组作为实参时,其实是传递了数组首元素的地址过来。
练习1: 完成9、10题。
3、数组作为函数的返回值,情况是如何的?
#include <stdio.h>int *fun()
{ int i; int A[5] = {1,2,3,4,5}; for(i=0;i<5;i++) { printf("A[%d]:%d\n",i,A[i]); }return A;
}int main(int argc,char *argv[])
{ int i; int *A = fun(); for(i=0;i<5;i++) { printf("A[%d]:%d\n",i,A[i]); } return 0; }编译: warning: function returns address of local variable
//你要返回一个地址可以,但是这个地址上的东西可能会失效。 结果: 1,2,3,4,5 段错误。 -> 因为数组返回时,只是返回数组的首元素的地址,因为返回之后,数组所在的空间就会被释放,所以64位不会返回数组首元素的 地址,而是会返回NULL。解决方案:
1)将数组设置为全局变量。 int A[5] = {1,2,3,4,5}; -> 数组在fun()返回时,不会释放。 int *fun() { int i; for(i=0;i<5;i++) { printf("A[%d]:%d\n",i,A[i]); } printf("A = %p\n",A); return A; }2)在数组定义前面加static关键词进行修饰
int *fun() { int i; static int A[5] = {1,2,3,4,5}; -> 加了static关键词之后,数组就不会在栈区申请空间,而是在data区申请空间,也就是说函数返回时,该数组的空间不会释放。 for(i=0;i<5;i++) { printf("A[%d]:%d\n",i,A[i]); } printf("A = %p\n",A); return A; }二、二维数组。
1、什么是二维数组? 二维数组在内存中是线性排列,不存在行与列的关系。 其实二维数组也是一个一维数组来的,只是这个一维数组中每一个成员都是一个一维数组。例如:
整型数组: int A[5] -> 每一个成员都是int类型的数据。 二维数组: 数组 A[5] -> 每一个成员都是一个数组。2、定义数组,只需要交代两件事情。
1)数组元素的个数 2)每一个数组元素的数据类型。 -> 基本数据类型/非基本数据类型定义数组的步骤:
例如1: 定义具有5个int类型数据的数组。第一步:确定一个数组名 A
第二步:确定数组中元素的个数,使用[]括住他,跟在数组名后面 A[5] 第三步:确定数组中每一个成员是什么 int a 第四步:将第3步的结果的变量名去掉 int 第五步:将第4步的结果写在第2步结果的前面就可以 int A[5] -> 最终结果。例子2: 定义一个二维数组,有2个成员,每一个成员都是具有3个int类型的数据。
第一步:确定一个数组名 B
第二步:确定数组中元素的个数,使用[]括住他,跟在数组名后面 B[2] 第三步:确定数组中每一个成员是什么 int x[3] 第四步:将第3步的结果的变量名去掉 int [3] 第五步:将第2步的结果写在第4步的结果的中间 int B[2][3] -> 最终结果。分析:int B[2][3]
代表这个数组有2个成员,每一个成员都是具有3个int类型的数组。3、二维数组的赋值。
1)定义的同时初始化。 int B[2][3] = { {1,2,3},{4,5,6}};2)先定义,后初始化。
int B[2][3]; B[0][0] = 1; B[0][1] = 2; B[0][2] = 3; B[1][0] = 4; B[1][1] = 5; B[1][2] = 6;4、研究二维数组的名字。
&B -> 二维数组的地址 类型: int (*)[2][3] B -> 二维数组的首元素的地址 -> &B[0] 类型: int (*)[3] B[0]-> 二维数组的首元素的首元素的地址 -> &B[0][0] 类型: int * B[0][0] -> 二维数组的首元素的首元素的值 类型: int5、解引用。
1)解引用二维数组的名字,得到什么? int B[2][3] = { {1,2,3},{4,5,6}}; *B = *&B[0] = B[0] = &B[0][0] -> 二维数组的首元素的首元素的地址。2)解引用二维数组的首元素的名字,得到什么?
*B[0] = *(&B[0][0]) = B[0][0] -> 二维数组的首元素的首元素的值。#include <stdio.h>
int main(int argc,char *argv[])
{ int B[2][3] = { {1,2,3},{4,5,6}}; printf("&B = %p\n",&B); //int(*)[2][3] printf("B = %p\n",B); //int(*)[3] printf("B[0] = %p\n",B[0]); //int* printf("&B+1 = %p\n",&B+1); //int(*)[2][3] printf("B+1 = %p\n",B+1); //int(*)[3] printf("B[0]+1 = %p\n",B[0]+1); //int* return 0; }练习2: 完成11、12、13题。
三、指针数组。
1、什么是指针数组?什么是数组指针? 数组指针是一个指针来的,这个指针指向一个数组的。 指针数组是一个数组来的,这个数组中每一个元素都是一个指针。2、如何定义指针数组?
例如1: 定义具有5个int类型数据的数组。
第一步:确定一个数组名 A
第二步:确定数组中元素的个数,使用[]括住他,跟在数组名后面 A[5] 第三步:确定数组中每一个成员是什么 int a 第四步:将第3步的结果的变量名去掉 int 第五步:将第4步的结果写在第2步结果的前面就可以 int A[5] -> 最终结果。例子2: 定义具有5个int*类型变量的数组。
第一步:确定一个数组名 B
第二步:确定数组中元素的个数,使用[]括住他,跟在数组名后面 B[5] 第三步:确定数组中每一个成员是什么 int*p 第四步:将第3步的结果的变量名去掉 int* 第五步:将第4步的结果写在第2步结果的前面就可以 int *B[5] -> 最终结果。分析:int *B[5]
数组名: B 成员个数: 5 每一个成员的类型: int*3、请问以下两句话的含义是什么?
int *p[5] -> 这是一个指针数组,这个数组中每一个成员都是int*类型的。
int (*p)[5] -> 这是一个数组指针,这个指针用于指向一个具有5个int类型数据的数组。
转载地址:http://emmpi.baihongyu.com/