C语言基础—复杂数据类型

------ android培训java培训、期待与您交流! ----------


数组:

我们之前学了一些基本数据类型:char,int,double,float

数组不是基本数据类型,是构造类型(有无数个基本数据类型组成)。

数组来存储一组数据。

格式: 类型  数组名[];  
如: int ages[5];
分配20个字节,每个元素4个字节(int)

简单使用:
* 简单初始化:int ages[5] = {1, 2, 3, 4, 5};
* 元素有顺序之分,每个元素都有一个唯一的下标(索引),从0开始
* 数组元素的访问:a[i];  i就是索引值

数组的长度:sizeof(ages)/sizeof(int);

数组的遍历:利用for循环
int main()
{
    int ages[5] = {1, 2, 3, 4, 5};
    for (int i = 0; i<(sizeof(ages)/sizeof(int)); i++)
    {
        printf("%d", ages[i]);
    }
    return 0;
}

数组初始化注意点:
一下写法都是对的
int ages[5] = {1,2,3,4,5};
int ages[5] = {1,2};
int ages[5] = {[2] = 3, [3] = 4};
int ages[] = {1,2,3};
但是下面这样写是不对的:
int ages[5];
ages = {1,2,3,4,5} ;
数组的地址是首元素的地址,刚初始化而没有元素,那么这个数组就没有地址,这样写不对。只能在定义数组的同时初始化。
int count = 5;
int ages[count] = {1,2,3};
这样写也是不对的,如果想要在定义数组的同时进行初始化那么[]里不能是变量。
再看这样:
int count = 5;
int ages[count];
ages[0] = 1;
ages[1] = 2;
这样写是可以的,但是,未赋值的空间会存储随机的数。

数组的内存存储:
* 数组的地址为首元素的地址
* 数组名可代表数组的地址

数组与函数:
void change(int array[]) // 这个可以看做指针,可以改变原数组元素
{
    array[0] = 200;
}
void change2(int a) // 这个是值传递,不能改变原数组元素
{
    n = 100;
}
int main()
{
    int ages[6] = {1, 2, 3, 4, 5, 6};
    change(ages);
    change(ages[0]);
    return 0;
}
所以:数组作为函数参数,传递是整个数组的地址,修改函数形参数组元素的值,会影响到外面的实参数组。
当一个数组作为变量参数来传递时,是被当做一个指针来使用的,长度不变都是8。

二位数组:
举个例子:
int ages[3][50];
这个ages 可以存放3个数组,每个数组可以存放50个元素。
int ages[3][5] = {
    {1,2,3,4,5},
    {1,2,3,4,5},
    {1,2,3,4,5}
}

字符串:

字符串可以说是几个字符数组。
"jack"------>'j', 'a', 'c', 'k', '\0' ;
是有这5个字符组成,‘\0’是字符串的结束标志,只一个隐藏的字符,每个字符串最后都会有一个隐藏的'\0'。

char name[10] = "jack";
printf("%s",name);
%s:输出一个数组或过个字符。
字符串最后的'\0' 可以防止多余输出。

strlen函数:
strlen函数是计算字符串的长度的
#include 
int main()
{
    atrlen("haha");
    return 0;
}
结果是4,包括后面的'\0'。

字符串数组:
char [2][10];
这个二维数组可以两个字符串,每个字符长的长度为10

指针:

最重要的数据类型,指针。
格式:类型 *变量名;
int *p;  指针都是占用8个字节(不管什么类型)。
int *p;
int a;
p = &a; // 把a的地址传给指针p,就可以利用p来修改变量a
*p = 10; // 访问p指针指向的空间,并修改
printf("%d", a);
结果 a = 10;传给指针的都是地址,指针根据地址找到变量的存储空间,以便于指针修改变量。

注意点:
* 指针的变量指向相同类型的变量,不然会访问对于的东西,类型不一样做的东西也不一样。
* 指针只能指向地址。
* 指针变量未初始化不要拿来间接访问其他储存空间。
int *p;
printf("%d", p); // 这样是不对的
* int *p = &a; 这样初始化是对的。

指向指针的指针:
int main()
{
    int a = 10;
    int *p = &a;
    int **p2 = &p;  // (int *)*p2 = &p;这个指针p2就是指向p
    return 0;
}

指针与数组:
指针和数组是密不可分的,有些情况,指针就是数组,数组就是指针。
int main()
{
    int ages[5] = {1, 2, 3, 4, 5};
    int *p;
    p = &ages[0];  // 数组第一个元素的地址就是数组的地址,也可以这么写 p = ages;
    // 这样p + 1就是ages[1],也就是说p + 1就指向数组的第二个元素的地址
    /*也就是说:
    *p == ages[0];
    *(p + 1) == ages[1];
    *(p + 2) == ages[2];
     也可以这样写:
    p[1] == *(p + 1);
    p[2] == *(p + 2)
    */  
    return 0;
}

注意点:
将数组作为变量进行传递时,数组将自动转换为指针。

指针与字符串:
与数组类似,char *name = "heima";  这就是常量字符串,里面的字符时不能改的。
如果利用数组定义一个字符串 char name[] = "heima";,这个字符串里面的字符是还可以修改的。

char *name = "heima";
这么写说明了指针name指向了“heima”首字符('h')的地址。

字符串的输入:
scanf("%s", name);

返回指针的函数:
char *test()
{
    char *name = "heima";
    return name;
}

指向函数的指针:
void (*p)(); // 固定写法,代表指针变量p指向函数
p = test; // 指向函数test
p(); // 调用了test函数

其他数据类型:

1. 结构体:

结构体也是构造类型。可以存储任何类型数据
格式:
结构体类型  结构体变量名
{
    结构体
};

需要两步:
1. 定义结构体
2. 设计变量
int main()
{
    struct Person
    {
        int age;
        double height;
        char *name;
    }

    struct Person p = {20, 1.55, "heima"};
    printf("age = %d", p.age);
    return 0;
}
这就是结构体,就是结构体的调用
给结构体赋值也可以这样写:
p.age = 20; 
p.height = 1.55;
p.name = "heima";
也可以这样写:
struct Person p = {.age = 20, .name = "heima", .height = 1.55};

我们也可以在定义了一个结构体类型,同时定义一个结构体变量:
struct Student 
{
    int age;
    char *name;
} stu;

还有一点(补齐算法),结构体的存储空间:
一般结构体所占的内存是所有变量所占空间之和,但是结构体所占的存储空间必须是最大成员的倍数,这就是补齐算法。

结构体数组:
int main()
{
    struct RankRecord
    {  
        int no;
        int score;
        char *name;
    }
    // 结构体数组
    struct RankRecord records[3] = 
    {
        {1, 5000, "jack"}, 
        {2, 2000, "jack"}, 
        {3, 1000, "jack"}
    }
    printf("%d", records[0].no); // 结构体数组读取
    return 0;
}


指向结构体的指针:
int main()
{
    struct Student
    {
        int no;
        int age;
    };
    struct Student stu = {1, 20};
    struct Student *p;
    p = &stu;
    // *p.age = 30; // 操作结构体
    // 也可以这样写,也是最长用的
    p->age = 30;
    printf("%d", p->age);
    return 0;
}
结构体嵌套:
 
   
 
   
 
  
int main()
{
    struct Date 
    {
        int year;
        int month;
        int day;
    }
    
    struct Strdent
    {
        int no;
        struct Date brithday;  // 这个地方就是嵌套了Date结构体
        struct Date ruxueDate; // 嵌套Date结构体
    }
    struct Student stu = {1, {2000, 9, 10}, {2012, 9, 10}};
    printf("%d", stu.brithday.year);
    return 0;
}

2. 枚举:

枚举:选值范围,固定取值
定义枚举类型
enum Season
{
    spring, summer, autum, winter
};
enum Season s = summer;
枚举主要是用于程序员之间的交流,增加代码的可读性。

------  android 培训 java 培训 、期待与您交流! ----------

你可能感兴趣的:(C基础)