您的位置:首页 > 娱乐 > 八卦 > 猎聘招聘官方网站_甘肃省卫健委网站官网_今日刚刚发生的军事新闻_市场营销手段13种手段

猎聘招聘官方网站_甘肃省卫健委网站官网_今日刚刚发生的军事新闻_市场营销手段13种手段

2025/2/24 11:30:54 来源:https://blog.csdn.net/2302_81805546/article/details/145056580  浏览:    关键词:猎聘招聘官方网站_甘肃省卫健委网站官网_今日刚刚发生的军事新闻_市场营销手段13种手段
猎聘招聘官方网站_甘肃省卫健委网站官网_今日刚刚发生的军事新闻_市场营销手段13种手段

欢迎拜访:雾里看山-CSDN博客
本篇主题:C语言之结构体
发布时间:2025.1.11
隶属专栏:C语言

在这里插入图片描述

目录

  • 结构体类型的声明
  • 结构体的自引用
  • 结构体变量的定义和初始化
  • 结构体成员访问
  • 结构体传参
  • 结构体内存对齐(重要部分)
    • 结构体对齐的规则
    • 常见结构体的计算
    • 为什么存在内存对齐
    • 修改默认对齐数

结构体类型的声明

结构体是一些值的集合,这些值称为成员变量,结构体的每个成员可以是不同类型的变量。
结构体内部的成员可以是标量、数组、指针、也可以是其他结构体。

声明

struct tag
{member-list;
}variable-list;

例如用结构体描述一个朋友

typedef struct friend
{char name[20];//名字int age;//年龄char sex[5];//性别char number[20]//电话号码
}friend;//结尾分号不能丢

特殊的声明
在对结构体进行声明的时候, 可以进行不完全声明。

struct
{int a;char b;float c;
}x;struct
{int a;char b;float c;
}a[20], *p;

上面的两个结构体在声明的时候,省略了结构体的标签

若对于以上代码执行p = &x;语句,则会报错。因为编译器会认为这是两个不同的结构体。

结构体的自引用

在结构体中包含一个类型为该结构体本身的结构体成员是否可以?

struct Node
{int data;struct Node next;//包含自身
};

不可以!! 不明白的可以想一下sizeof(struct Node)的结果是多少。上述代码会在初始化结构体的时候报错。

正确的引用方式如下:

struct Node
{int data;struct Node *next;	
};

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

struct Point
{int x;int y;
}p1;//声明类型的同时定义变量P1;
struct Point P2;//直接定义变量P2;//初始化:定义变量的同时赋初值
struct Point P3 = { x, y};struct Friend
{char name[20];int age;
};
struct Friend f = {"zhangsan", 20};//初始化struct Node
{int data;struct Point P;struct Node* next;
}n1 = {10, {4, 5}, NULL};//结构体嵌套初始化struct Node n2 = {20, {3, 4}, NULL};//结构体嵌套初始化

结构体成员访问

结构体变量访问内部成员是通过点操作符 . 对内部成员进行访问。点操作符接受两个操作数。
例如:
结构体f
当我们需要访问结构体内的成员nameage 时,可以进行如下操作

struct Friend f;
strcpy(f.name, "lisi");//使用.操作符访问name成员
f.age = 21;//使用.操作符访问age成员

在实际应用中,我们更多的时候是遇到结构体的指针,这时我们可以进行如下操作。

struct Friend
{char name[20];int age;
};void Print(struct Friend *pf)
{printf("name = %s   age = %d\n", (*pf).name, (*pf).age);//使用结构体指针访问指向对象的成员printf("name = %s   age = %d\n", pf->name, pf->age);
}int main()
{struct Friend f = {"zhangsan", 20};Print(&f);return 0;
}

结构体传参

我们仔细观察下面的代码。

struct Friend
{char name[20];int age;
};
//结构体传参
void Print1(struct Friend f)
{printf("name = %s   age = %d\n", f.name, f.age);
}
//结构体指针传参
void Print2(struct Friend *pf)
{printf("name = %s   age = %d\n", pf->name, pf->age);
}int main()
{struct Friend f = {"zhangsan", 20};Print1(f);//传结构体Print2(&f);//传结构体指针return 0;
}

在实际应用中,传结构体和传结构体指针哪个更好一点?

在函数传参的时候,参数是需要压栈的,如果传递结构体,当结构体太大的时候,参数压栈的系统开销会很大,结果则会导致性能的下降。
结论: 传结构体指针更优。

结构体内存对齐(重要部分)

结构体对齐的规则

  1. 第一个成员在与结构体变量偏移量为 0 的地址处。
  2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
    对齐数 = min(编译器默认对齐数, 该成员大小)
  3. 结构体总大小为最大对齐数(每一个成员变量都有一个对齐数)的整数倍。
  4. 如果嵌套了结构体, 嵌套的结构体先确定自己的大小,再按照上面的规则计算。

常见结构体的计算

以在VS编译器下为例(默认对齐数是8)

struct S1
{char c1;//编译器默认对齐数为8, 该成员大小1,对齐数1 int i;//编译器默认对齐数为8, 该成员大小4,对齐数4char c2;//编译器默认对齐数为8, 该成员大小1,对齐数1 
};
printf("%d\n", sizeof(struct S1));//最终大小为12
struct S2
{int i;//编译器默认对齐数为8, 该成员大小4,对齐数4 char c1;//编译器默认对齐数为8, 该成员大小1,对齐数1 char c2;//编译器默认对齐数为8, 该成员大小1,对齐数1 
};
printf("%d\n", sizeof(struct S2));//最终大小为8
struct S3
{double d;//编译器默认对齐数为8, 该成员大小8,对齐数8 char c;//编译器默认对齐数为8, 该成员大小1,对齐数1 int i;//编译器默认对齐数为8, 该成员大小4,对齐数4 
};
printf("%d\n", sizeof(struct S3));//最终大小为16
struct S4
{char c1;//编译器默认对齐数为8, 该成员大小1,对齐数1 struct S3 s3;//编译器默认对齐数为8, 该成员大小16,对齐数8 double d;//编译器默认对齐数为8, 该成员大小8,对齐数8 
};
printf("%d\n", sizeof(struct S4));//最终大小为32

在这里插入图片描述

为什么存在内存对齐

  1. 平台原因(代码的可移植性):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件只能在某些地址处取某些特定类型的数据,否则则会抛出异常。
  2. 性能问题:数据结构(尤其是栈),应该尽可能的在自然边界上对齐原因在于,为了访问未对齐的内存,处理器需要做两次内存访问; 而对齐的内存只需要访问一次即可。

总体来说 : 结构体的内存对齐是拿空间换取时间的做法。

在设计的时候,要让占用空间小的尽量在一起,这样即满足对齐,又可以节省空间。

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

S1和S2内部成员函数相同,但是S2所占的空间却小于S1。

除此之外,还可以修改默认对齐数

修改默认对齐数

在结构体对齐方式不合适的时候, 我们可以自己更改默认对齐参数。
使用#pragma这个预处理命令可以更改我们的默认对齐数。

#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 mian()
{printf("S1 = %d\n", sizeof(struct S1));printf("S2 = %d\n", sizeof(struct S1));return 0;
}

⚠️ 写在最后:以上是我对C语言结构体部分的一些学习后的总结, 如有错误或者需要补充的地方欢迎各位大佬私信我交流!!!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com