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]);

  • 相关阅读:
    Composite in Javascript
    Model Validation in Asp.net MVC
    HttpRuntime.Cache vs. HttpContext.Current.Cache
    Controller Extensibility in ASP.NET MVC
    The Decorator Pattern in Javascript
    The Flyweight Pattern in Javascript
    Model Binding in ASP.NET MVC
    Asp.net MVC
    jQuery Ajax 实例 全解析
    ASP.NET AJAX入门系列
  • 原文地址:https://www.cnblogs.com/cj5785/p/10664761.html
Copyright © 2011-2022 走看看