感觉c这块的内容真的无比枯燥,但在整理的过程中确实又学会了很多

这篇主要讲c语言里的结构体共用体

一、结构体

1. 声明和使用

结构体是C编程中一种用户自定义的数据类型,类似于Java的JavaBean

1
2
3
4
5
6
7
8
9
10
11
12
13
// 一般定义变量 student a 
struct Student
{
char name[50];
int age;
} student,a;


//使用typedef定义
typedef struct{
char name[50];
int age;
} Student;

当结构体需要内存过大,使用动态内存申请。结构体占用字节数和结构体内字段有关,指针占用内存就是4/8字节,因此传指针比传值效率更高。

1
2
3
4
Student *s = (Student*)malloc(sizeof(Student));
memset(s,0,sizeof(Student));

printf("%d\n", s->age);

2. 字节对齐

内存空间按照字节划分,理论上可以从任何起始地址访问任意类型的变量。

但实际中在访问特定类型变量时经常在特定的内存地址开始访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序一个接一个地存放,这就是对齐。

字节对齐的问题主要就是针对结构体。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
struct Struct1
{
short a;
int b;
short c;
};
struct Struct2
{
short a;
short c;
int b;
};


// short = 2 补 2
// int = 4
// short = 2 补 2
sizeof(Struct1) = 12

// 2个short在一起组成一个 4
// int = 4
sizeof(Struct2) = 8
  • 指定对齐位数

    #pragma pack(n)的意思是告诉编译器字节对齐方式为n字节对齐,n字节对齐就是说变量存放的起始地址的偏移量有两种情况:

    • 第一、如果n大于等于该变量所占用的字节数,那么偏移量必须满足默认的对齐方式,

    • 第二、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。

    结构的总大小也有个约束条件,分下面两种情况:

    如果n大于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数;否则必须为n的倍数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #pragma pack(2) //指定以2字节对齐
    struct MyStruct1
    {
    short a;
    int b;
    short c;
    };
    #pragma pack() //取消对齐

    //short = 2
    //int = 4 用2的倍数进行对齐
    //short = 2

二、共用体

在相同的内存位置存储不同的数据类型

共用体占用的内存应足够存储共用体中最大的成员

1
2
3
4
5
6
7
8
9
10
11
12
//占用4字节
union Data
{
int i;
short j;
}
union Data data;

data.i = 1; 1

//i的数据损坏
data.j = 1.1f; 1

共用体在一般的编程中应用较少,在单片机中应用较多。

代码

https://github.com/ddssingsong/AnyNdk


 评论