黑马程序员_iOS开发C语言基础之结构体

来源:互联网 发布:大连 旅游 知乎 编辑:程序博客网 时间:2024/05/09 01:10

1、结构体的基本使用

#include <stdio.h>

/*

 数组:只能由多个相同类型的数据构成

 结构体:可以由多个不同类型的数据构成

 

 */

int main()

{

    //int age1;//定义整型变量方法

    

    //结构体类型 结构体变量名 ,结构体类型默认不存在,自己来定义类型,不行基本数据类型,如int系统存在,但是构造数据类型系统不存在。

    

    //定义结构体的类型,是告诉计算机系统这种类型中所包含的数据都有哪些

    //1.定义结构体类型

    

    struct person

    {

        //里面的3个变量,可以称为是结构体的成员或者属性

        int age;

        double height;

        char* name;

    };

    

    //int ages[3] = {2,3,4};

    // ages = {2, 3, 4};错误,因为ages是常量地址

    //2.根据结构体类型,定义结构体变量

    struct person p = {201.55"jack"}; // p为结构体变量名,类型名为person,但是因为是结构体,定义变量时,关键字struct不能省略。

    p.age = 30;

    p.name = "rose";//和数组的初始化很像,如果不在定义变量时初始化,之后初始化,只能给成员单独初始化,不能再同一初始化赋值了。

    printf("age=%d, name=%s, height=%f\n", p.age, p.name ,p.height);

    

    struct person p2;

    //p2 = {25,1.65,"tom"}这种写法是错误的,只能在定义结构体变量的同时才能统一赋初值。

    //就像数组一样,数组名代表地址,数组的地址不可随便改,也就是地址常量,常量不可改变

    p2.age = 25;

    p2.height = 1.65;

    p2.name = "tom";

    //如果赋初值时,可以用如下方式实现不按顺序赋初值。

    //就像数组int pen[2]={[1]=1, [0]=2};必须告诉系统哪个值赋给哪个属性

    struct person p3 = {.height = 1.44, .name="apple", .age=12};

    

    return 0;

}

2、结构体的内存分析

#include <stdio.h>


int main()

{

    return 0;

}


// 补齐算法

void test1()

{

    struct student

    {

        int age;//4个字节

        char* name//8个字节,不是5个字节,指针类型都是占用8个字节

        // char name[];

    };

    struct student stu;

    stu.age = 20;

    stu.name = "jack";

    

    int s = sizeof(stu);

    printf("%d\n",s);//输出结果位16,原因补齐算法(对齐算法),结构体变量所占字节是最大成员变量所占字节的整倍数,如上指针占8个字节,所以4+8=1212不是8的整倍数,补齐后为16。这与计算机组成原理有关。

    //结构体所占用的存储空间,必须是最大成员字节数的倍数

 

}


//结构体内存分析细节

void test()

{

    //1.定义结构体类型(并不会分配内存存储空间)

    struct date

    {

        int year;

        int month;

        int day;

    };

    //定义结构体类型,是不会分配存储空间的,就像系统不会为int类型分配存储空间一样,只有在定义数据类型变量时才会分配存储空间。

    // int a;

    //2.定义结构体变量(真正分配存储空间)

    struct date d1 = {2011410};//09表示是八进制,因为以0开头

    struct date d2 = {201289};

    //会将d1所有成员的值对应地赋值给d2的所有成员

    d2 = d1;

    printf("%d,%d ,%d\n",d1.year,d1.month,d1.day);

    printf("%d,%d ,%d\n",d2.year,d2.month,d2.day);

    printf("%p - %p - %p\n",&d1.year, &d1.month, &d1.day);//就像数组一样定义不同的数组变量时,先分配大的内存地址,但每个数组成员是按由大到小的顺序排在每个数组变量的内存中,year地址最小,day地址最大。

    int s = sizeof(d1);

    printf("s=%d\n",s);

}



3、定义结构体多种方式

//定义结构体多种方式

void test()

{

    /*

     1.定义结构体变量的3种方式

     1> 先定义类型,再定义变量(分开定义)

     struct student

     {

     int age;

     };

     struct student stu1;

     

     2> 定义类型的同时定义变量

     struct student

     {

     int age;

     }stu1;

     struct student stu2;

     

     3> 定义类型的同时定义变量(省略了类型名称)

     struct

     {

     int age;

     }stu;

     struct

     {

     int age;

     }stu1;

     */

    

    /*定义结构体变量的第3种方式

     struct

     {

     int age;

     double height;

     char* name;

     }stu;

     //缺点是下次再定义变量时,要重新复制,因为结构体类型不能重用

     struct

     {

     int age;

     double height;

     char* name;

     }stu2;

     */

    

    

    /*错误写法:结构体类型重复定义,就像重复定义变量一样

     struct student

     {

     int age;

     double height;

     char* name;

     }stu;

     struct student

     {

     int age;

     double height;

     char* name;

     }stu2;//会报错,结构体类型struct student重复定义

     */

    

    /*结构体类型不能重复定义

     struct student

     {

     int age;

     };

     struct student

     {

     double height;

     };

     struct student stu;

     */

    

    /*

     这句代码做了两件事情:

     1.定义结构体类型

     2.利用新定义好的类型来定义结构体变量

     

     //定义变量的第2种方式:定义类型的同时定义变量

     struct student

     {

     int age;

     double height;

     char* name;

     }stu;   //相当于int a;

     struct student stu2;

     */

    //*************************************

    /*

     // 定义变量的第1种方式

     // 1.定义结构体类型

     struct student

     {

     int age;

     double height;

     char* name;

     };

     

     //2.定义结构体类型变量

     struct student stu = {20, 1.78, "jack"};

     */

}


4、结构体作用域

#include <stdio.h>

/*

    结构体类型的作用域

    1> 定义在函数外面:全局有效(从定义类型的那行开始,一直到文件结尾)

    2> 定义在函数(代码块)内部:局部有效(从定义类型的那行开始,一直到代码块结束)

 */

//结构体类型也是有作用域的

//从这行开始,一直到文件结尾,都是有效(跟全局变量一样)

struct date

{

    int year;

    int month;

    int day;

};


int a ;


void test2()

{

    struct date d1 = {2011910};

    

    //假如在此函数内,再次定义和外部结构体相同的结构体类型,不会报错,作用域搞定,就像在外部定义int a;在内部还可以定义相同变量名,只是作用域不同,如下:

    int a;

    struct date

    {

        int year;

        int month;

        int day;

    };

    

    //结构体类型也是有作用域的,从定义类型的那一行开始,一直到代码块结束,所以main函数中不可以使用此结构体类型

    struct person

    {

        int age;

    };

    struct person p = {12};

}

/*结构体类型定义放到函数外面,之后的语句可以使用,就像全局变量一样。

struct date

{

    int year;

    int month;

    int day;

};

 

int a;

*/

int main()

{

    struct date d1 = {200989};

    

    test2();

    //不能使用test2函数中定义的类型

    //struct person p2;//会报错,因为结构体类型有作用范围,许多程序自定义的东西是有作用范围的,如变量是有作用范围的,结构体类型是自己定义的,所以也有作用范围,但int不是程序自定义,是系统自带的。

    return 0;

}


5、结构体数组

#include <stdio.h>


int main()

{

    struct rankRecord

    {

        int no; // 序号 4

        char* name; // 名称 8

        int score; // 积分 4

    };

    /*

    struct rankRecord r1 = {1, "jack", 5000};

    struct rankRecord r1 = {2, "jim", 500};

    struct rankRecord r1 = {3, "jake", 300};

    */

    //int ages[3];

    //int ages[3] = {11, 22, 33};

    /*

    char* names[3] =

    {

        {jack},

        {jim},

        {jake}

    };

    */

    //对齐算法

    //能存放3个结构体变量,每个结构体变量占16个字节

    struct rankRecord records[3] =

    {

        {1"jack"5000},

        {2"jim"500},

        {3"jake"300}

    };

    //错误写法

    //records[0] = {4, "rose", 9000};//这种赋值修改,只能在定义结构体变量的同时才可以。

    

    // 正确写法,修改方法如下:

    records[0].no = 4;//可以修改第一条数据的no属性,其他属性同理。

    

    for(int i=0; i<3; i++)

    {

        printf("%d\t%s\t%d\n",records[i].no, records[i].name, records[i].score);

    }

    

    return 0;

}




6、指向结构体的指针

#include <stdio.h>

/*掌握:

 1.指向结构体的指针的定义

    struct student* p;

 

 2.利用指针访问结构体的成员

    1> 结构体变量明发.成员名称

    2> (*p).成员名称

    3> p->成员名称

 */

int main()

{

    struct student

    {

        int no;

        int age;

    };

    // 结构体变量

    struct student stu = {120};

    //stu.age = 30;

    

    //根据指向整型的指针的定义,类推出指向结构体的指针。

    // int* p;

    // int a;

    //p = &a;

    // pirntf("%d\n", a);

    // pirntf("%d\n", *p);

    

    // 指针变量p将来指向struct student类型的数据。

    struct student* p;

    //万变不离其宗,使指针变量p指向结构体变量stu方法如下

    p = &stu;

    

    //利用指针变量间接访问所指向结构体变量成员

    // 第一种访问方式

    printf("no = %d, age=%d\n", stu.no ,stu.age);

    // 第二种方式

    printf("no = %d, age=%d\n", (*p).no ,(*p).age);

    // 第三种方式(使用中最常见的方式)

    printf("no = %d, age=%d\n", p->no , p->age);

    

    //同访问方式一样,修改方式也是三种,原理一样

    stu.age = 30;

    (*p).age = 30;

    p->age = 30;

    

    return 0;

}




7、结构体的嵌套定义

#include <stdio.h>

int main()

{

    //定义结构体类型

    /*

    struct studen

    {

        int no;

     

        int year; // 这种定义方法不好

        int month;

        int day;

     

        int year2;

        int month2;

        int day2;

    };

    */

    struct date

    {

        int year;

        int month;

        int day;

    };

    struct student

    {

        int no; // 学号

        /*int year;

        int month;

        int day;*/

        //此行定义代替以上三行定义

        struct date birthday; // 生日,

        struct date ruxuedate; // 入学日期

        struct student stu; // 这种写法是错误的,不能自己包含自己的定义

    };

    

    struct student stu =

    {

        1, {2000910}, {2012910}

    };

    

    printf("year=%d,month=%d,day=%d\n",stu.birthday.year, stu.birthday.month, stu.birthday.day);

    return 0;

}


0 0
原创粉丝点击