当前位置: 首页 > 文档资料 > C 语言程序设计 >

数组

优质
小牛编辑
140浏览
2023-12-01

数组

///01.数组.c
#include <stdio.h>
#include <stdlib.h>

//01.采用容器结构存储数据的要点:
//  1.必须为每个数据分配独立的存储空间
//  2.必须为每个数据分配独立的标识符(变量名称)
//02.C语言之C99语法的特点:
//  针对于VC编译器:
//      1.VC编译器分配数组的时候必须静态分配
//          静态分配:在编译时期确定数组所占据的内存尺寸(字节数)大小
//      2.数组长度必须为真常量(或常量表达式)
//          明确的数组元素个数
//  针对于GCC编译器:
//      1.GCC编译器分配数组的时候采用动态分配
//          动态分配:在执行时期确定数组所占据的内存尺寸
//      2.数组长度可以为伪常量(或变量)
//          不确定的数组元素个数(程序执行时期知道)
//03.伪常量的声明方式:
//  在原始变量的前面添加一个伪常量标识前缀("const")
//04.关于常量的透彻分析:
//  伪常量:const int num = 1;
//      1.具备内存实体:
//          不允许直接进行修改,但允许间接进行修改
//      2.静态分配:
//          在编译时期确定伪常量的值
//  真常量:#define NUM 1
//      1.不具备内存实体:
//          既不允许直接修改,也不允许间接修改
//      2.预编译决定:
//          在预编译时期就已经决定了将宏名为了常量(整型,实型,字符型,字符串型)
int main01(void)
{
    const int num = 10;//常量表达式{但是该常量表达式的常量值可以经过间接改变,所以是伪常量}-->有内存实体
    #define NUM 1//真常量{一旦确定了真常量的值,就不允许修改真常量的数据}-->无内存实体

    //int a[num];//编译的时候确定大小,静态分配,VC不支持
    int a[NUM];
    //VC必须静态分配,GCC可以动态分配

    system("pause");
}

//05.关于数组使用的要点总结:
//  1.静态数组分配方式:
//      (1).int a[5] = {1, 2, 3, 4, 5};//数组元素的类型:int;数组整体的名称:a;数组元素的个数:5;
//          数组元素的具体数据:1, 2, 3, 4, 5
//      (2),静态分配:在编译时期就已经确定了数组所占用的内存地址以及内存尺寸(首地址+尺寸)
//  2.分配方式组成分析:
//      (1).int:表明数组当中所存储的每个元素的类型
//      (2).a:表示数组整体的名称(数组名)
//          数组名的本质是一个常量指针(伪常量)
//      (3).{}:代码块儿分配方式,只能用于声明数组的同时进行使用(既可以局部初始化也可以全部初始化)
//  3.sizeof:
//      (1).是一个关键字,而不是一个函数
//      (2).如果传递的是数组名,那么求取的内存尺寸是数组整体所占用的内存尺寸(区分数组整体和数组元素)
//  4.%p和%d的使用意义:
//      (1).所以数据在内存当中的存储实质都一样,都是二进制数据
//      (2).格式控制符只是决定了不同的解析方式:
//          %d:内存数据按照有符号十进制(signed int)类型进行解析
//          %p:内存数据按照指针意义进行解析
//  5.数组元素以及数组元素的地址:
//      a[i]:a[i]表示数组元素的名称,直接写数组元素的名称,相当于访问该数组元素本身(数据)
//          好比叫一个人的名字,目的就是为了这个人知道
//      &a[i]:&表示根据变量的名称(内存实体)获取该变量的地址
//          变量的名称:其实就是内存实体的别名(区分:(变量:内存实体)-->(变量名称:变量别名))
//          统称:变量(统一)-->具称:变量别名(唯一)
//      说明:中括号"[]"的优先级高于取内存实体地址符"&"的优先级
int main02(void)
{
    //0,1,2,3,4
    int a[5] = { 1,2,3,4,5 };//a:数组名称,a代表该数组的内存首地址

    printf("%d \n", sizeof(a));//sizeof(a):用于获取数组所占用的真实内存尺寸(字节大小)
    printf("%p \n", a);//数组的内存首地址
    for (int i = 0; i < 5; i++)
    {
        printf("%d, %p \n", a[i], &a[i]);//i:索引;&:符号表示获取变量的内存首地址
    }

    system("pause");
}

//06.数组元素本身(内存实体)和数组元素地址(内存实体地址)
//  1.数组元素地址(内存实体地址)
//      &a[i],a+i:数组默认从第0个开始进行索引划分(数组元素(内存实体)的标识符:索引)
//  2.数组元素本身(内存实体):
//      a[i],*(&a[i]),*(a+i)
int main03(void)
{
    //数组声明语法:double a[10];数组元素的类型 数组整体的名称[数组元素的个数];
    double a[10] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0 };

    printf("%d \n", sizeof(a));//10*8=80
    for (int i = 0; i < 10; i++)
    {
        //&a[i], a + i;//代表数组第i个元素的内存实体地址,等价关系a+i(与类型密切相关)//以0作为开头
        //a + (i - 1)*sizeof(double);//以1作为开头
        //*号表示根据内存实体的地址获取内存实体本身(数据内容)
        //a[i], *(&a[i]), *(a + i);//效果等价
        printf("%lf, %lf, %lf, %p, %p \n", a[i], *(&a[i]), *(a + i), &a[i], a + i);//下标,索引
    }

    system("pause");
}

数组初始化

///02.数组初始化语法.c
#include <stdio.h>
#include <stdlib.h>

//01.数组的初始化方式:
//  标准方式:
//      int a[5] = {1, 2, 3, 4, 5};
//      数组元素的类型 数组整体的名称[数组元素的指明个数] = {静态初始化的静态数据};
//  简化方式:
//      itn a[] = {1, 2, 3, 4, 5};
//  注意事项:
//      1.C/C++当中的静态数组必须进行静态初始化才能进行使用,Java当中的静态数组会进行默认初始化
//          大括号:{}就是表明静态初始化
//      2.数组的声明必须明确两点:数组元素的数据类型+数组元素的元素个数-->才能确定数组整体尺寸(内存字节数)
//      3.赋值特点:
//          (1).大括号这种静态初始化方式,只能适用于声明数组的状态下(声明并定义的情况之下)
//          (2).统一赋值与指明赋值特点:
//              统一赋值:{0}
//              指明赋值:
//                  完全赋值:
//                      {1, 2, 3, 4, 5}
//                  前置局部:
//                      {1, 2, 3}-->后面默认被编译器初始化为0,只有当前面进行了指明初始化的情况,后面才会进行默认初始化为0的操作
//      4.访问特点:
//          访问数组整体的内部某个元素本身(内存实体本身),不会出错
//          访问数组整体的外部某个元素本身(内存实体本身),可能出错,可能不出错(关键是看系统是否为该内存实体分配了使用权限)
int main04(void)
{
    //int a[10] = { 0 };//C/C++当中的数组必须进行初始化
    //int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };//明确数组初始化元素个数,可以省略数组元素个数的声明
    //int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };//数组初始化不允许越界
    //int a[10] = { 1, 2, 3, 4 };//默认没有初始化值的数组元素都将会被默认的初始化为0
    int a[5] = { 0 };//数组必须明确其元素个数

    for (int i = 0; i < 10; i++)
    {//注意不存在长度部分的数据将会是无法预料的值,5之后的数据可能会出现问题
        printf("%d \n", a[i]);
    }

    system("pause");
}

//02.数组名称的操作:
//  1.任何指针进行加法,乘法,除法都没有任何实际意义
//  2.在同一个数组当中的不同内存实体的内存地址进行
//      减法运算具备实际意义,用于获取两个数组元素之间的元素个数差值
//  3.C语言的常规数组不能进行整体操作,元素本身(内存实体)可以进行整体操作
//  4.C语言的特殊素组(字符数组),如果以'\0'结尾,那么就是一个正常的字符串模拟
//      字符串结尾标识符必须是'\0'(字符\0)-->0或者'\0'都一样
//      字符:'\0'-->ASCII:0-->以及关键字NULL
int main05(void)
{
    int a[5] = { 1, 2, 3, 4, 5 };
    int b[5] = { 2, 3, 4, 5, 6 };

    //a = b;//数组名称:标识数组整体的内存空间,数组名称是一个常量指针,不可以直接进行修改
    //a[1];//访问整体数组a当中的第1个元素所对应的内存实体(数据本身)
    //a + b;//C语言当中的普通数组不可以进行批量草最,只能针对于某一个元素进行批量操作
    //a < b;
    char str[5] = { 'c', 'a', 'l', 'c', NULL };   
    printf("%s \n", str);

    system("pause");
}