C语言结构体

为什么使用结构体?

  1. 在实际工作中,很多数据是有内在联系的,一般是成组出现,如:姓名、性别和年龄等,为了体现它们的内在联系,就需要一个能够存放多种不同类型数据的数据结构。

  2. C 语言是面向过程的语言,但是面向对象的思想才更加接近实际,结构体的使用,就好比 C++ 中的类,结构体让面向对象编程的思想可以在 C 语言中得到应用。

声明一个结构体类型

PS:(不分配内存,就相当于一个数据类型,只有定义了具体变量才分配内存)

/* 结构体类型为 struct student */
struct student {
    char name[64]; /* 结构体成员 */
    unsigned char sex;
    int age;
    int number;
};

定义结构体类型变量

一般常用的有如下两种方法:

  1. 先声明结构体类型,再使用类型名 变量名 的方法定义结构体类型的变量
#include <stdio.h>

/* 声明一个结构体类型为 struct student */
struct student {
    char name[64];
    unsigned char sex;
    int age;
    int number;
};

int main()
{
    /* 定义结构体变量 */
    struct student stu; /* 类型名 变量名 */
    printf("the size of struct student is %ld\n", sizeof(stu));
    return 0;
}

运行结果

$ ./a.out 
the size of struct student is 76

输出结果跟我们想象的不太一样,按理说应该是 64 + 1 + 4 + 4 = 73(Bytes),实际打印出来却是 76 字节,这是因为 4 字节对齐。

  1. 在声明类型的同时定义变量
#include <stdio.h>

struct student {
    char name[64];
    unsigned char sex;
    int age;
    int number;
}stu; /* 声明时定义结构体 */

匿名结构体

#include <stdio.h>

/* 匿名结构体 */
struct {
    char name[64];
    unsigned char sex;
    int age;
    int number;
}stu; /* 不能再用来定义结构体变量 */

由于没有结构体名,而类型名是由 struct 结构体名 组成,因此不能再用来定义其它结构体变量,只能在声明结构体类型时定义。

结构体初始化

  1. 定义时初始化
#include <stdio.h>

int main()
{
    /* 声明结构体类型 */
    struct student {
        char name[64];
        unsigned char sex;
        int age;
        int number;
    };

    /* 定义并初始化 */
    struct student stu = {"shelmean", 1, 22, 1};

    /* 引用结构体成员 */
    printf("name:%s\n", stu.name);
    printf("sex:%d\n", stu.sex);
    printf("age:%d\n", stu.age);
    printf("number:%d\n", stu.number);

    return 0;
}

运行结果

$ ./a.out 
name:shelmean
sex:1
age:22
number:1
  1. 声明时定义并初始化
#include <stdio.h>

int main()
{
    struct student {
        char name[64];
        unsigned char sex;
        int age;
        int number;
    }stu = {"shelmean", 1, 22, 1};

    /* 引用结构体成员 */
    printf("name:%s\n", stu.name);
    printf("sex:%d\n", stu.sex);
    printf("age:%d\n", stu.age);
    printf("number:%d\n", stu.number);

    return 0;
}

运行结果

$ ./a.out 
name:shelmean
sex:1
age:22
number:1
  1. 匿名结构体初始化
#include <stdio.h>

int main()
{
    struct {
        char name[64];
        unsigned char sex;
        int age;
        int number;
    }stu = {"shelmean", 1, 22, 1};

    /* 引用结构体成员 */
    printf("name:%s\n", stu.name);
    printf("sex:%d\n", stu.sex);
    printf("age:%d\n", stu.age);
    printf("number:%d\n", stu.number);

    return 0;
}

运行结果

$ ./a.out 
name:shelmean
sex:1
age:22
number:1
  1. 指定成员初始化
#include <stdio.h>

int main()
{
    /* 声明一个结构体类型 */
    struct student {
        char name[64];
        unsigned char sex;
        int age;
        int number;
    };

    /* 定义并初始化指定成员 */
    struct student stu = {
        .name = "shelmean",
        .age = 22
    };

    /* 引用结构体成员 */
    printf("name:%s\n", stu.name);
    printf("sex:%d\n", stu.sex);
    printf("age:%d\n", stu.age);
    printf("number:%d\n", stu.number);

    return 0;
}

运行结果

$ ./a.out
name:shelmean
sex:0
age:22
number:0

其它未被初始化的整型成员被系统初始化为 0 , 字符型成员被初始化为 ‘\0’ ,指针型成员被初始化为 NULL。

如何使用结构体成员 ?

结构体变量名 . 成员名

就如上面引用结构体成员的例子。

结构体大小

正如上面的例子,理论上算下来,应该是 64 + 1 + 4 + 4 = 73(Bytes),而实际上却是 76 。这是为什么?

这里 gcc 编译器是以 4 字节对齐,所以是 76 字节。

如上面的成员 name 占 64 个字节,是 4 的倍数,因此从 sex 开始又是一个 ‘字’ 的开始,虽然成员 sex 只占一个字节,但是其它 3 个字节不够下一个 int 型的 成员 age 变量来存储,因此 3 个字节空着,从下一个字开始存成员 age。因此结构体大小为 64 + 4 +4 + 4 = 76 。如果 sex 后面的一个成员是 1 个字节,那么不会从下一个字开始,而是接着 sex 后面占用一个字节,空 2 个字节,也就是说 sex 变量后面再定义一个 char 类型的成员,并不会改变该结构体的大小。

如:

#include <stdio.h>

/* 匿名结构体 */
struct {
    char name[64];
    unsigned char sex;
    unsigned char test; /* 添加一个 1 字节的变量,并不会影响结构体大小 */
    int age;
    int number;
}stu;

int main()
{
    printf("the size of struct student is %ld\n", sizeof(stu));
    return 0;
}

运行结果

$ ./a.out 
the size of struct student is 76
posted @ 2018-08-05 19:17  shelmean  阅读(293)  评论(0)    收藏  举报