<<C>> 结构体

简介: <<C>> 结构体

1.结构体

1.1结构体的声明

1. struct tag
2. {
3.     member-list;
4. }variable-list;


例如我们可以描述一个学生:

struct Stu
{
 char name[20];//名字
 int age;//年龄
 char sex[5];//性别
 char id[20];//学号
}; //分号不能丢

1.2结构体的自引用

在结构中可以包含一个类型为该结构体本身的成员,但是要使用指针(类似链表)

错误方式:
struct Node
{
 int data;
 struct Node next;
};  //不可行,sizeof(struct Node)是多少?无限大,没有结束的地方
正确方式:
struct Node
{
 int data;
 struct Node* next;//注意不能去掉srruct
};//需要有一个指向NULL

1.3结构体变量的定义和初始化

struct Point
{
 int x;
 int y; }p1; //声明类型的同时定义变量p1
struct Point p2; //定义结构体变量p2
//初始化:定义变量的同时赋初值。
struct Point p3 = {x, y};
struct Stu        //类型声明
{
 char name[15];//名字
 int age;      //年龄
};
struct Stu s = {"zhangsan", 20};//初始化
struct Node
{
 int data;
 struct Point p;
 struct Node* next; 
}n1 = {10, {4,5}, NULL}; //结构体嵌套初始化
struct Node n2 = {20, {5, 6}, NULL};//结构体嵌套初始化


1.4结构体内存对齐(重难点)

学习结构体对齐=====探讨结构体的大小,这也是面试容易考的地方

内存对齐的优点:拿空间换取时间,提高性能


对齐的规则:


 1. 第一个成员在与结构体变量偏移量为0的地址处。

2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。

对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。

VS中默认的值为8

3. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。

4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整

体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。  

                可以参考图然后看着对齐规则,看一下就会了


c34616f8fd484d9aa5a9c7e7c843ac20.jpg


练习题:

//练习1
struct S1
{
 char c1;//第一个成员从偏移量为0的地方开始
 int i;//int大小为4个字节 需要从偏移量为4的地方开始 
 char c2;//从偏移量为8的地方开始
};
printf("%d\n", sizeof(struct S1));//一共占 1(c1)+3(浪费)+4(i)+1(c2)+3(浪费)=12
//练习2
struct S2
{
 char c1;
 char c2;
 int i;
};
printf("%d\n", sizeof(struct S2));
//练习3
struct S3
{
 double d;
 char c;
 int i;
};
printf("%d\n", sizeof(struct S3));
//练习4-结构体嵌套问题
struct S4
{
 char c1;
 struct S3 s3;
 double d;
};
printf("%d\n", sizeof(struct S4));


在设计代码的时候我们要尽量让空间小的成员集中在一起,有利于节省空间

比如下面的代码,成员一样,但是占的空间却不一样

struct S1
{
 char c1;
 int i;
 char c2;
};
struct S2
{
 char c1;
 char c2;
 int i;
};

1.5修改默认的对齐数

结构在对齐方式不合适的时候,我么可以自己更改默认对齐数              

#pragma pack ( )

#include <stdio.h>
#pragma pack(8)//设置默认对齐数为8
struct S1
{
 char c1;
 int i;
 char c2;
};
#pragma pack()//取消设置的默认对齐数,还原为默认
#pragma pack(1)//设置默认对齐数为1
struct S2
{
 char c1;
 int i;
 char c2;
};
#pragma pack()//取消设置的默认对齐数,还原为默认
int main()
{
    //输出的结果是什么?
    printf("%d\n", sizeof(struct S1));
    printf("%d\n", sizeof(struct S2));
    return 0;
}

1.6结构体传参

最好使用传地址的方式进行传参,因为传输整个结构体,占用空间比较大,参数压栈系统开销较大,会导致性能下降

struct S {
 int data[1000];
 int num;
};
struct S s = {{1,2,3,4}, 1000};
//结构体传参
void print1(struct S s) {
 printf("%d\n", s.num);
}
//结构体地址传参
void print2(struct S* ps) {
 printf("%d\n", ps->num);
}
int main()
{
 print1(s);  //传结构体
 print2(&s); //传地址
 return 0; 
}



相关文章
|
10月前
|
存储 C语言
C 结构体
C 结构体。
25 0
|
3月前
|
存储 算法 数据安全/隐私保护
结构体
结构体
37 1
|
2月前
|
编译器 Linux C语言
浅谈结构体
浅谈结构体
22 1
|
3月前
|
编译器 Linux C语言
结构体(详解)
结构体(详解)
39 1
|
3月前
|
算法 C语言
结构体相关知识
结构体相关知识
|
3月前
|
算法 程序员 C++
|
9月前
|
机器学习/深度学习 存储 编译器
Day_16 结构体
Day_16 结构体
|
3月前
|
Java 编译器 Linux
再次认识结构体
再次认识结构体
56 0
|
12月前
|
编译器 C++
|
12月前
|
编译器