zoukankan      html  css  js  c++  java
  • 深入理解C语言-深入理解数组

    数组,作为C语言中常见的复杂数据类型,了解其本质有助于深入了解C语言

    数组概念

    元素类型角度:数组是相同类型的变量的有序集合测试指针变量占有内存空间大小
    内存角度:联系的一大片内存空间
    数组概念

    数组初始化

    数组元素的个数可以显示或隐式指定
    数组的初始化可以用{ 0 },也可以使用memset初始化

    int main()
    {
    	int i = 0;
    	int a[10] = { 1, 2 }; //其他初始化为0
    	int b[] = { 1, 2 };
    	int c[20] = { 0 };
     
    	for (i = 0; i < 10; i++)
    	{
    		printf("%d ", a[i]);
    	}
    	memset(a, 0, sizeof(a));
    	getchar();
    	return 0;	
    }
    

    关于数组名的一些问题

    1. 数组首元素的地址和数组地址是两个不同的概念,前者代表一个元素大小,后者代表一个和数组大小
    2. 数组名代表数组首元素的地址,它是个常量,其本质就是一个变量的别名
    3. 数组首元素的地址和数组的地址值相等
    4. 数组的类型由元素类型和数组大小共同决定,e.g. int[5]

    数组类型的自定义

    typedef int(MYINT5)[5];
    ···
    MYINT5i Array; //int Array[5];
    

    数组指针

    数组指针用于指向一个数组

    1. 通过数组类型定义数组指针
    typedef int(ArrayType)[5];
    ArrayType* pointer;
    

    用数组类型加*定义一个数组指针

    void main(void)
    {
        int a[5];//声明一个数组类型
        typedef int(MYINT5)[5];//用数组类型 加*,定义一个数组指针变量
        MYINT5 *array;
        array = &a;
    
        for (i = 0; i < 5; i++)
        {
            (*array)[i] = i;
        }
        
        for (i = 0; i < 5; i++)
        {
            printf("
    %d %d", a[i], (*array)[i]);
        }
    }
    
    1. 声明一个数组指针类型
    typedef int (*MyPointer)[5];
    

    定义一个数组指针类型,然后用类型定义变量

    void main(void)
    {
        int b[5];//声明一个数组指针类型
    	typedef int (*MyPointer)[5];//用数组指针类型,去定义一个变量
    	MyPointer mypoint;
    	mypoint= &b;
    
    	for (i = 0; i < 5; i++)
    	{
    		(*mypoint)[i] = i;
    	}
    
    	for (i = 0; i < 5; i++)
    	{
    		printf("
    %d %d", b[i], (*mypoint)[i]);
    	}
    }
    
    1. 直接定义
    int (*pointer)[n];
    

    直接定义一个数组指针变量

    void main(void)
    {
        int c[5];
    	int (*pointer)[5] = &c;//直接声明一个数组指针变量
    	for (i = 0; i < 5; i++)
    	{
    		(*pointer)[i] = i;
    	}
    
    	for (i = 0; i < 5; i++)
    	{
    		printf("
    %d %d", c[i], (*pointer)[i]);
    	}
    }
    

    一维数组本质

    int a[5] 一维数组名代表数组首元素的地址
    int a[5] ==> a的类型为int*

    二维数组本质

    实验:

    int arr[3][4];
    printf("arr:%d, arr + 1:%d", arr, arr + 1);
    

    此时输出打印的结果相差16,也就是4 * 4,通过这个契机,得出二维数组名的本质
    arr的本质是一个数组指针,每次向后移动一维的长度

    说明 写法 写法 写法
    第0行第1列元素地址 a [0]+1 *a+1 &a[0][1]
    第1行第2列元素地址 a [1]+2 *(a+1)+2 &a[1][2]
    第 i 行第 j 列元素地址 a [i]+j *(a+i)+j &a[i][j]
    第1行第2列元素的值 *(a [1]+2) *( *(a+1)+2) a[1][2]
    第 i 行第 j 列元素的值 *(a [i]+j) *( *(a+i)+j) a[i][j]

    正是因为有了这些特性,二维数组在做函数参数的时候,会退化为二级指针,这样设计的目的在于参数传递的时候不用传递太多数据,数组指针做函数参数,一般只会使用到二维
    char buf[3][4] ==> char buf[][4] ==> char (*buf)[4]

    多维数组的线性存储特性

    多维数组在内存中是线性存储的,即按照低维到高维线性排序

    char buf[2][3];
    

    buf[0][0]·buf[0][1]·buf[0][2]·buf[1][0]·buf[1][1]·buf[1][2]

    数组做函数参数

    由于C语言中只会以机械式的值拷贝的方式传递参数(实参把值传给形参),所以在数组做函数参数的时候,是没法知道数组大小的,需要额外传递数组大小数据

    int fun(char a[20], size_t b)
    {
       printf("%d	%d",b,sizeof(a));
    }
    

    二维数组可以看做是一维数组
    二维数组中的每个元素是一维数组
    二维数组参数中第一维的参数可以省略
    void f(int a[5]); ==> void f(int a[]); ==> void f(int* a);
    void g(int a[3][3]) ==> void g(int a[][3]); ==> void g(int (*a)[3]);

  • 相关阅读:
    springboot配置redis缓存
    【spark】local模式运行
    mybatis从入门到精通(二) 增删查改
    学习设计模式
    学习设计模式
    mybatis从入门到精通(一) 入门
    学习NIO 之 使用方法
    学习 NIO 之 零拷贝
    Java并发
    学习设计模式
  • 原文地址:https://www.cnblogs.com/cj5785/p/10664760.html
Copyright © 2011-2022 走看看