您的位置:首页 > 编程语言 > C语言/C++

C语言 - 结构体struct

2020-01-15 12:01 1506 查看

结构体:struct,用户自己设计的 不同类型组合的 组合数据类型
        格式
        调用结构体
        结构体的打印
                指针与结构体的结合
                引用与结构体结合
        结构体的套接
        结构体:内存对齐
共用体:union,共用内存,达到对不同的类型进行解析的目的
        共用体的用法

//quesiton:如何实现CSDN博客间的跳转

格式:

[code]    struct Student{
char name[20];  //姓名
int num[20];  //学号
int age;  //年龄
char group;  //所在学习小组
float score;  //成绩
};

调用结构体:

[code]int main(){
Student student; //定义结构体变量

student.s_age=22;//给结构体内部赋值

student.s_name[20]="xiaoxuxu";  //×
//结构体内若是一个数组或者字符串,不能直接赋值
//需要用拷贝函数
strcpy(s1.s_name,"string");

//可以整体打印? 答案:不可以
//除了整体初始化外,其余的都是分开操作,一个一个打印出来
}

访问并修改结构体内部数据:

    1.逐个赋值: 使用 . (成员访问符)

    2.整体赋值: Student s1 = {"LU","201901",18,"A",80}; // 利用花括号整体一一对应初始化

                           //注意:结构体内部为int num[20];  赋值的时候是201901

                               //当结构体内部为char num[20]; 赋值的时候是"201901"

                           //注意:初始化时,不能跳着初始化(略过其中属性)

                        Student s2 = s1; //整体赋值 本质是调用内存拷贝函数 my_memmove(&s3,&s1,sizeof(Student));

 结构体的打印:

[code]//值传递:直接开辟了一个Student类用来打印
void Print_Student(Student stu){printf: stu.s_name , stu.s_num....}
main:Print_Student1(stu1);

//指针:指针只开辟4个字节,相对节省空间,
//缺点:为了防止不小心改变pstud的指向的内容 需要在前面加const 防止指向的内容被修改
//缺点:使用指针 一定要判空,防止空指针的存在
void Print_Student1(Student const *pstud)
{
if(NULL == pstud) return ;
printf: pstud->s_name , pstud->s_num....
}
main:Print_Student2(&stu1); //指针传递的是地址

//引用(起小名):避免开辟空间造成的空间浪费
void Print_Student1(Student const &stu){printf: stu.s_name , stu.s_num....}
main:Print_Student1(stu1);

              指针与结构体的结合:(指向作用  -> )

[code] ps ->s_age = 10; //ps指针指向s1
(*ps).s_age = 10; //等价
//.和*的优先级  =>  .的优先级first

              引用与结构体结合:

[code]//引用与结构体的结合:
Student &s = s2;//定义了一个Student类的变量s2,给s2起小名叫s

结构体的套接:

          结构体可以套接结构体,但是函数不可以套接函数

                                                               (函数内部可以申明函数,不可以新定义一个函数)

[code]//定义函数    //×
int Add(int x int y){
return x+y;
}

//申明函数    //√
int Add(int x int y);
int fun(int ,int );
[code]//结构体套接结构体:
struct Date
{
int year;
int month;
};
struct Student
{
char s_id[20];
struct Date birthday; //定义一个Date型的结构体变量 birthday
};

//=========等价=========

struct Student
{
char s_id[20];
struct Date
{
int year;
int month;
};
struct Date birthday; //struct 在.cpp文件中可以省略
};

结构体:内存对齐(存疑)

内存对齐遵循原则:

  1.当前成员所在的地址 能够整除 成员本身的字节大小 (不包括数组)
  2.结构体的整体大小能够能整除除成员最大基本类型 大小(不包括数组)         
  3.从零地址开始

另一种理解:
偏移量
:结构体中的偏移量就是结构体成员结构体变量地址之差
计算结构体大小的规则:
  1.每一个成员的偏移量都必须是该成员的倍数。
  2.结构体的大小必须是该结构体字节数最大成员的倍数。

[code]例如下面的结构体:
struct A
{
char a;
short b;
int c;
};
/*第一个成员的偏移量都是0;一般可以不看,a的大小为1,所以成员b的偏移量为1,b的大小
为2,1不是2的倍数,所以应该将1+1,成为2的倍数,成员c的偏移量就为1+1+2,是成员c的
倍数,现在就符合计算结构体大小的第一条:改成员的偏移量是该成员大小
的倍数,还有第二条规则:结构体大小是结构体最大成员的倍数,结构体的大小就是各个成员
之和,a;2,b:2,c:4加起来就是8,该结构最大成员为c大小为4,满足第二个条件,所以该结
构体的倍数就是8*/

参考博客:https://www.cnblogs.com/smile-812/p/7897187.html 

[code]struct AA
{
char a;   // 1 + 3
short b; //  4
int c;   // 4
double d;  // 8
};  //16

struct A
{
char a;   // 1 + 3   [0,1,2,3] (1,2,3浪费)
int b;    // 4  [4,5,6,7]
}; //[0-7]  大小为8,向前对齐

struct A1
{
char a;   //1
char c;   //1
int b;    //4
}s; // 大小为8

struct B
{
char a;   //1 + 1  [0,1]
short b;  //2  [2,3]
int c;    // 4  [4,5,6,7]
}; //   [0-7]大小为8,向前对齐

struct C
{
char a;   // 1 + 3  [0,1,2,3]
int b;    // 4  [4,5,6,7]
short c;  // 2 + 6  [8-15]
double d; // 8  [16-23]
}; // [0-23]大小为24,向前对齐

struct D
{
char a;   // 1 [0]
char b;   // 1 [1]
short c;  // 2 [2,3]
int d;    // 4 [4,5,6,7]
}; // [0-7]大小为8,向前对齐

struct E
{
char a;   // 1 + 1 [0,1]
short c;   // 2 [2,3]
char b;  // 1 + 3 [4,5,6,7]
int d;  // 4 [8,9,10,11]
}; // [0-11]大小为12,向前对齐

struct F
{
int a;  // 4 [0,1,2,3]
char c; // 1 + 3  [4,5,6,7]
}; //[0-7]大小为8,向后对齐,一般只有两个数据成员

struct G
{
char ch[17];  //17 + 3  20能被4整除
int i; // 4
float f; //4
}su;  // 大小为28

struct H
{
char  a;  //1 +1
short b;   //2
char  c;  //1 +3
int   d;  //4
char  e[3]; //3 +1
};   // 大小为16

干预内存对齐:
#pragma pack(n)  // n = 1,2,4,8,16
                             //n = 1;强制要求内存按照1字节对齐;

共用体:

共用体:共用内存 ;; 最主要的用途 : 对不同的类型进行解析
结构体:自己独占内存,所占内存是各成员占用内存长度之和(存在内存对齐)

[code]union A{
char a;
short b;
int c;
};
struct B{
char a;
short b;
int c;
};

int main(){
A x1;
//x1.a = 'a'; //这里内存互相侵占了
//x1.b = 12;

B x2;
x2.a = 'a'; //自己用自己的 不影响
x2.b = 12;
}

共用体的用法:

 共用体的用法:对同一个空间按不同类型去识别
    //共用体可以套用结构体
    //结构体可以套用联合体

[code]//直接使用共用体
union Node{
unsigned int addr;
unsigned char s1,s2,s3,s4;
//对于联合体而言s1,s2,s3,s4都用的是同一个字节
};

//共用体套用结构体
union Node{
unsigned int addr;
sruct{
unsigned char s1,s2,s3,s4; //分布于四个字节了
};
}

//结构体套用共用体
struct Node{
char ch;
union{ //无名共用体:哑元结构
int a; //a和f共享同一个内存
float f;
};//1+4 =6 凑/4 =>8个字节
};

//这里还需深一步理解,为何要这么做! 每种结构都有什么好处

 

  • 点赞
  • 收藏
  • 分享
  • 文章举报
AKUANer 发布了65 篇原创文章 · 获赞 0 · 访问量 1101 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: