9.C语言(复合类型--结构体-共同体)

简介: 结构体1.结构体定义和初始化#define _CRT_SECURE_NO_WARNINGS#include #include //定义一个结构体【类型】//strut 是关键字//struct Worker合起来才是结构体类型//结构体...

结构体

1.结构体定义和初始化
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
//定义一个结构体【类型】
//strut 是关键字
//struct Worker合起来才是结构体类型
//结构体内部定义的变量不能直接赋值
//结构体只是一个类型,没有定义变量前,
//是没有分配空间的,不能赋值(C与C++不同,C++可以在定义的时候赋值)
struct Worker {
    int age;
    char name[5];
    int score;
};//必须有分号
int main() {
    //定义结构体【变量】
    //类型名 变量名
    struct Worker wo;

    //第一种初始化方式,和数组一样,使用大括号
    struct  Worker wo2 = {20,"hahah",100};

    //第二种初始化方式
    struct Worker wo3;
    wo3.age = 21;
    //name是数组名,数组名是常量,不能直接赋值修改使用strcpy
    //wo3.name = "zhangsan";
    strcpy(wo3.name, "zhangsan");
    wo3.score = 99;

    //第三种初始化方式,通过指针,使用->
    struct Worker *p;
    p = &wo3;
    p->age = 22;
    p->score = 90;
    strcpy(p->name, "lisi");

    //任何结构体变量都可以用.或->操作成员
    //wo3取地址就是一个指针
    (&wo3)->age = 11;
    //p加上一个*就是它指向的内存,也就是wo3
    (*p).age = 12;

    system("pause");
}
2.定义结构体变量的方式

1.先声明结构体类型,再定义变量名

struct Worker {
    int age;
    char name[5];
    int score;
};
struct Worker wo;

2.在声明类型的同时定义变量

struct Worker {
    int age;
    char name[5];
    int score;
}wo,wo2;

3.直接定义结构体类型变量(匿名,无类型名),这种方式定义的结构体,无法在外部定义其他的结构体变量,只能使用已经定义好的

struct {
    int age;
    char name[5];
    int score;
}wo,wo2;
3.结构体数组的定义和赋值

第一种初始化方式

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

struct Worker {
    int age;
    char name[10];
    int score;
};
int main() {
    struct Worker wo;

    //定义一个结构体数组
    struct  Worker a[5];
    
    //给第一个结构体元素赋值
    a[0].age = 18;
    strcpy(a[0].name, "ren");
    a[0].score = 50;

    //给第二个结构体元素赋值
    (a + 1)->age = 10;
    strcpy((a + 1)->name, "zhen");
    (a + 1)->score = 30;

    //给第三个结构体元素赋值
    (*(a + 2)).age = 20;
    strcpy((*(a + 2)).name, "ming");
    (*(a + 2)).score = 9;

    //定义一个指针指向这个结构体数组
    struct Worker *p = a;

    //给第四个结构体元素赋值
    p[3].age = 21;
    strcpy(p[3].name, "ying");
    p[3].score = 100; 

    //给第五个结构体元素赋值
    (p + 4)->age = 32;
    strcpy((p + 4)->name, "zi");
    (p + 4)->score = 10;
    
    int i = 0;
    int n = sizeof(a) / sizeof(a[0]);
    for (i = 0; i < n; i++) {
        printf("%d,%s,%d\n", p[i].age, p[i].name, p[i].score);
    }

    
    system("pause");
}

第二种初始化方式,下边a a1 a2都是初始化一个结构体数组

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

struct Worker {
    int age;
    char name[10];
    int score;
};
int main() {
    struct Worker a2[5] =
    {
        {11,"a",12},
        {12,"b",13},
        {13,"c",14},
        {14,"d",15},
        {15,"e",16}
    };

    struct Worker a3[5] = {
        11,"a",12 ,
        12,"b",13,
        13,"c",14,
        14,"d",15,
        15,"e",16
    };
    struct Worker a[5] = {
        11,"a",12 ,12,"b",13,13,"c",14,14,"d",15,15,"e",16
    };
    int i = 0;
    int n = sizeof(a) / sizeof(a[0]);
    for (i = 0; i < n; i++) {
        printf("%d,%s,%d\n", a[i].age,a[i].name, a[i].score);
    }

    
    system("pause");
}
4.结构体嵌套
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

struct Manager {
    int salary;
    int year;
};

struct Worker {
    int age;
    struct Manager m;
};

int main() {
    //定义一个结构体Worker变量
    struct Worker w;

    //通过结构体变量给这个结构体赋值
    w.age = 20;
    w.m.salary = 20000;
    printf("%d,%d\n", w.age,w.m.salary);

    //定义一个结构体指针指向这个结构体,通过指针赋值
    struct Worker *p = &w;
    p->age = 21;
    p->m.salary = 30000;
    p->m.year = 2018;
    printf("%d,%d,%d\n", w.age, w.m.salary,w.m.year);

    //直接在定义的时候初始化赋值,这种赋值形式可读性很差
    struct Worker woker = {22,19999,2019};
    printf("%d,%d,%d\n", woker.age, woker.m.salary,woker.m.year);
    system("pause");
}
5.相同类型的结构体变量可以相互赋值
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

struct Manager {
    int salary;
    int year;
};

int main() {

    //相同类型的变量可以通过=号赋值
    int a = 10;
    int b;
    b = a;
    printf("%d\n",b);

    //相同类型的结构体变量也可以相互赋值
    struct Manager s1 = {20000,2018};
    struct Manager s2;
    s2 = s1;
    printf("%d,%d\n",s2.salary,s2.year);
    system("pause");
}
6.结构体的值传递

结构体值传递和普通数据类型的值传递原理是相同的,把结构体变量m2传递到setManager方法中,相当于把m2的值赋给了形参m(相同类型的结构体变量可以赋值),此时m和m2内存中存储的值是相同的,但是二者没有直接联系,然后在方法setManager中给m中的元素重新赋值,打印结果如下,可以看出,方法执行完成后销毁,原来的m2的内存空间并不受影响

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

struct Manager {
    int salary;
    int year;
};
void setManager(struct Manager m) {
    m.salary = 1000;
    m.year = 2018;

    printf("setManager %d %d\n", m.salary, m.year);
}
int main() {
    struct Manager m2 = {10000,2019};
    setManager(m2);
    printf("setManager %d %d\n", m2.salary, m2.year);
    system("pause");
}

打印

setManager 1000 2018
setManager 10000 2019
请按任意键继续. . .

7.结构体的地址传递
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

struct Manager {
    int salary;
    int year;
};
void setManager(struct Manager *m) {
    m->salary = 1000;
    m->year = 2018;

    printf("setManager %d %d\n", m->salary, m->year);
}

int main() {
    struct Manager m2 = {10000,2019};
    setManager(&m2);
    printf("setManager %d %d\n", m2.salary, m2.year);
    system("pause");
}

打印
setManager 1000 2018
setManager 1000 2018
请按任意键继续. . .

8.结构体指针指向栈区空间
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

struct Manager {
    int salary;
    int year;
};

int main() {
     //在栈内存定义一个结构体变量
    struct Manager m;

    //定义一个结构体指针指向结构体变量m
    struct Manager *p;
    p = &m;

    p->salary = 1999;
    p->year = 2018;

    printf("%d %d\n", m.salary, m.year);
    system("pause");
}
9.结构体指针指向堆区空间
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

struct Manager {
    int salary;
    int year;
};

int main() {
    struct Manager *p;

    //在堆内存开辟一块空间并由p指向它
    p = (struct Manager*)malloc(sizeof(struct Manager));
    if (p == NULL) {
        printf("malloc err\n");
        return 0;
    }

    p->salary = 1999;
    p->year = 2018;

    printf("%d %d\n", p->salary, p->year);

    if (p != NULL) {
        free(p);
        p = NULL;
    }

    system("pause");
}
10.结构体中的指针变量
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

struct Manager {
    int salary;
    int year;
    char *name;
};

int main() {
    struct Manager m;
    //在堆区开辟空间并由结构体中的成员变量指向它
    //这里是在堆区开辟空间由它指向这个空间,当然也
    //可以在栈中定义一个变量由这个指针指向他
    m.name =(char *) malloc(strlen("renzhenming") + 1);
    strcpy(m.name, "renzhenming");
    m.salary = 10000;
    m.year = 2019;

    printf("%d %d %s\n", m.salary, m.year,m.name);

    if (m.name != NULL) {
        free(m.name);
        m.name = NULL;
    }

    system("pause");
}

共同体(共用体 联合体)

由于共同体中所有成员公用同一份内存,所以共同体中不可以同时操作两个或两个以上得元素,因为当你操作其中一个,加入给其中一个附了值,那么另一个值就会发生变化,因为内存已经改变了,如下程序中,共同体所占内存为4个字节,因为int最大,int占4个字节,给c赋值0x44332211后,刚好占满内存,由于abc所指向得首地址是相同得,所以a指向从首地址开始第一个字节,那么打印就是11,b指向从首地址开始前两个字节,那么打印就是2211,c指向从首地址开始到结尾这块内存,打印就是44332211


img_8e5fc5caf91d7b7a71a71cd68af2c16b.png
共同体内存分布.png
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

union Manager {
    unsigned char a;
    unsigned short b;
    unsigned int c;
};

int main() {
    //结构体大小可以简单得认为是成员大小得累加
    //共同体得大小为最大成员得大小,成员中最大得是int,所以打印为4
    printf("%lu\n", sizeof(union Manager));

    //共同体共有一块内存,所有成员地址都一样
    union Manager m;
    printf("%p,%p,%p,%p\n", &m,&m.a,&m.b,&m.c);

    //给某个成员赋值,会影响到另外得成员
    //左边是高位,右边是低位
    //高位放高地址,低位放低地址
    m.c = 0x44332211;
    printf("m.c = %x\n",m.c);
    printf("m.a = %x\n", m.a);
    printf("m.b = %x\n", m.b);

    m.a = 00;
    printf("m.c = %x\n", m.c);
    printf("m.a = %x\n", m.a);
    printf("m.b = %x\n", m.b);
    system("pause");
}

未完,待续...

`

相关文章
|
10天前
|
存储 C语言
C语言程序设计核心详解 第九章 结构体与链表概要详解
本文档详细介绍了C语言中的结构体与链表。首先,讲解了结构体的定义、初始化及使用方法,并演示了如何通过不同方式定义结构体变量。接着,介绍了指向结构体的指针及其应用,包括结构体变量和结构体数组的指针操作。随后,概述了链表的概念与定义,解释了链表的基本操作如动态分配、插入和删除。最后,简述了共用体类型及其变量定义与引用方法。通过本文档,读者可以全面了解结构体与链表的基础知识及实际应用技巧。
|
16天前
|
C语言
c语言中的结构体
本文档详细介绍了C语言中结构体的使用方法,包括结构体的基本定义、变量声明与赋值、数组与指针的应用,以及结构体嵌套、与`typedef`结合使用等内容。通过示例代码展示了如何操作结构体成员,并解释了内存对齐的概念。
|
22天前
|
C语言
C语言结构体赋值的四种方式
本文总结了C语言结构体的四种赋值方式,并通过示例代码和编译运行结果展示了每种方式的特点和效果。
34 6
|
1月前
|
编译器 程序员 Linux
【C语言篇】结构体和位段详细介绍
跟结构相⽐,位段可以达到同样的效果,并且可以很好的节省空间,但是有跨平台的问题存在。
|
1月前
|
存储 自然语言处理 编译器
C语言中的char类型
C语言中的char类型
|
1月前
|
C语言
C语言中的复合语句
C语言中的复合语句
|
1月前
|
算法 编译器 API
C语言中的longdouble类型
C语言中的longdouble类型
|
1月前
|
存储 C语言
C语言------结构体和共用体
这篇文章是关于C语言中结构体和共用体的实训,通过示例代码演示了结构体的定义、赋值、使用,以及如何使用结构体变量进行数据的组织和操作,包括输入、排序、求平均分和查找学生信息等功能。
C语言------结构体和共用体
|
3月前
|
编译器 测试技术 C语言
【C语言】:自定义类型:结构体的使用及其内存对齐
【C语言】:自定义类型:结构体的使用及其内存对齐
50 7
|
3月前
|
网络协议 编译器 Linux
结构体(C语言)
结构体(C语言)