C与C++成长之路——c提高四之数组

一、一维数组初始化

int a[]= { 1, 3, 5 }; //3个元素
int b[5]= { 1,2,3 } ; lla[3], a[4]自动初始化为0
int c[10]= { 0 }; //全部元素初始化为0
memset(c, 0, sizeof(c));//通过memset给数组每个元素赋值为0

二、数组类型

针对32位

int a[] = { 1, 3, 5 }; //3个元素
a :数组首行首元素地址,一级指针
&a:整个数组的首地址,二级指针

//首行首元素地址和首行(整个一维数组)地址值虽然是一样,但是它们的步长不一样
a+l:跳过1元素,一元素为4字节,步长4个字节
&a+l:跳过整个数组,整个数组长度为3*4 =12,步长3* 4 = 12
sizeof(a):传参为:数组首行首元素地址,测数组(int [3])的长度,3* 4 = 12,只要把数组名传进去,就是测整个数组
sizeof(a[0]):传参为:数组首元素(不是地址),每个元素为int类,4字节
sizeof(&a):传参为:一维数组整个数组的地址(首行地址),编译器当做指针类型,4字节

(重要)首行地址-->首行首元素地址(加*)
&a:首行地址
*&a->a :首行首元素地址

//数组也是一种数据类型,类型本质:固定大小内存块别名
1/由元素类型和内存大小(元素个数)共同决定int a[5]int[5]
//可以通过typedef定义数组类型
//有typedef:类型
//没有typedef:变量
typedef int ARRARY[5];//定义了一个名字为ARRARY的数组类型
/等价于typedef int(ARRARY)[5];
//根据数组类型,定义变量
//ARRARY的位置替代为d,去掉typedef,int d[5]
ARRARY d;//相当于int d[5];

三、数组指针变量(它是指针变量,指向数组的指针)

//定义数组变量
int a[10];
//有typedef:类型
//没有typedef:变量
  1. 根据数组类型,定义指针变量,数组指针变量
typedef int ARRARY[10];//定义了一个名字为ARRARY的数组类型
//等价于typedef int(ARRARY)[10];
ARRARY*p;//数组指针变量
/编译会有警告,但不会出错,因为a和&a的值一样,就算p = a这样赋值,编译器内部也会自动转换为p = &a。不建议这么做
p= a ;
//p指向a数组,指向一维数组的指针
p= &a ;
//如何操作数组指针变量p
int i = 0 ;
for(i =0; i <10; i++)
{
    (*p)[i]= i + 1;
    //p = &a
    //l*p -> * ( &a)-> a
    //(*p)[i] -> a[i]
}
  1. 直接定义数组指针变量(常用)
// ()[]同级,从左往右看
//()有*,它是一个指针,[]代表数组
//指向数组的指针变量,[]中的数字代表指针+1的步长
int (*p)[10];

//p 指向a数组,指向一维数组的指针
p = &a;
  1. 先定义数组指针类型,再根据类型定义指针变量(常用)
//数组指针类型,加上typedef
typedef int (*Q)[10];
Q p;//根据类型定义变量,p是数组指针变量
p = &a; //p指向数组a

四、多维数组的本质

  1. 二维数组初始化
int a1[3][4]= {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9, 10, 11, 12}
        };
int a2[3][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
int a3[][4]= { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
  1. 内存中并不存在多维数组,多维数组在内存中都是线性存储
int a[3][5]= {0};
int *b = (int *)a ;
int i = 0;
for(i = 0; i <15; i++)
{
    printf("%d ", b[i]);
}
  1. 多维数组名
//学会类比
int b[5]= {0};
b:首行首元素地址,+l,跳4个字节
&b:首行地址,+1,跳4*5= 20个字节

//二维数组实际上就是N个一维数组,把二维数组第一个[]的值看做标志位,0-> 2,第0个一维数组a[5]->第2个一维数组a[ 5]
int a[3][5]= { 0 } ;
a:
二维数组首元素地址
代表首行地址,相当于一维数组整个数组的地址,相当于上面的&b,本来就是一个二级指针

//(重要)首行地址-->首行首元素地址(加*)
*a:首行首元素地址,相当于一维数组首元素地址,相当于上面的b

a + i-> &a[i]:第i行地址
//(重要)某行地址-->某行首元素地址(加*)
*(a+i) -> *&a[i] -> a[i]:第i行首元素地址
//第i行j列元素的地址,某行首元素地址 +偏移量
*(a+i)+j -> a[i]+j-> &a[i][]:第i行j列元素的地址
//第i行j列元素的值,第i行j列元素的地址的基础上(加*)
*(*(a+i)+j) -> a[i][j]:第i行j列元素的值

int a[3][5] = { O };
sizeof(a):二维数组整个数组长度,4 *3 *5 = 60
sizeof(a[0][0]): a[0][0]为第0第0列元素(是元素,不是地址),测某个元素长度:4字节
sizeof(a[0]): a[0]为第0行首元素地址,相当于测第0行一维数组的长度:4 *5 = 20
  1. 多维数组名,实际上是一个数组指针,指向数组的指针,步长为一行字节长度
int a[3][5]= {0 };
//定义一个数组指针类型的变量
int (*p)[5];
//编译会有警告,但不会出错,因为a和&a的值一样,但是&a代表整个二维数组的首地址,就算p = &a这样赋值,编译器内部也会自动转换为p = a
//不建议这么做
p = &a ;
//a本来就是第0个一维数组整个数组的地址,所以,无需加&
p = a ;
  1. 二维数组做形参的三种形式
//一维救组做函数参数退化为一级指针
//二维数组(多维数组)做函数参数,退化为数组指针
int a[3][5]= { 0 };
void print_arrayl(int a[3][5]);

//第一维的数组,可以不写,第二维必须写,代表步长,确定指针+1的步长5*4
void print_array2(int a[][5])

//形参为数组指针变量,[]的数字代表步长
void print_array3 (int (*a)[5]);

// a+1和二维数组的步长不一样
//这里的步长为4
//上面二维数组的步长为5 *4 = 20
void print_array3 (int **a) ; //error

五、指针数组(它是数组,每个元素都是指针)

1.指针数组的定义

//指针数组变量
//[]优先级比*高,它是数组,r每个元素都是指针(char *)
char *str[]= {"111", "2222222"};
char **str = { "111", "2222222"}; //error,指针只能指向一个内存区域
  1. 指针数组做形参
void fun(char *str[]) ;
void fun (char **str) ; //str[]-> *str
  1. main函数的指针数组

//argc : 传参数的个数(包含可执行程序)
//argv : 指针数组,指向输入的参数
int main (int argc, char *argv[]);
: demo.exe a b test
int argc = 4
char *argv[]= { "demo.exe", "a", "b", "test"}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值