首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >C语言、结构体

C语言、结构体

原创
作者头像
xieliyu
发布2026-09-20 21:58:25
发布2026-09-20 21:58:25
610
举报

前言:

  C语言也给我们程序员规定了一种自定义 类 型,结构体的每一个成员可以是不同类型的变量,结构是⼀些值的集合,这些值称为成员变量,那么结构体的内存大小又是怎么算的呢?

1. 结构体类型声明定义

  结构是⼀些值的集合,这些值称为成员变量;关键字:struct

代码语言:c
复制
#include<stdio.h>
struct add//结构体的声明定义
{
 int a;
}value;//value指的是这个结构体的名字   旁边这个分号必须要添加  value可以先不写,等我们需要的时候创建就行了
//比如
int main()
{
 struct add s1 ;//我们创建的时候就能够这么写
 return 0;
}

  这就是简单的结构体声明

  假设当我们想要描述一个学生的时候。

代码语言:c
复制
struct stu
{
 char name[20];
 int age;
 float Score;
};

  这就简单创建了一个简单结构体类型。


2. 结构体的创建和初始化

  就拿我们的学生这个结构体来讲

代码语言:c
复制
#include<stdio.h>
struct stu//结构体声明定义
{
 char name[20];
 int age;
 float Score;
};
int main()
{
 //struct stu s1;这个是结构体的创建,类型位struct stu 名字位:s1
 //结构体的创建和初始化
 struct stu s1 = {"zhangsan",20,95.5f};//这就是我们简单的初始化,也可以部分初始化,或者不初始化。
 //当我们想不按照这个顺序初始化的时候我们就要用到这个操作符
 struct stu s2 = {.age = 20,.Score = 95.5f,.name = "zhangsan"};
 return 0;
}
结构体的打印:
代码语言:c
复制
#include<stdio.h>
struct stu//结构体声明定义
{
 char name[20];
 int age;
 float Score;
};
int main()
{
 struct stu s2 = {.age = 20,.Score = 95.5f,.name = "zhangsan"};
 //打印
 printf("%d\n",s2.age);
 printf("%f\n",s2.Score);
 printf("%s\n",s2.name);
 return 0;
}
在这里插入图片描述
在这里插入图片描述
结构的特殊声明:

比如:

代码语言:c
复制
//这样类型的特殊声明
struct 
{
 char name[20];
 int age;
 float score;
}value;

//还有这样的结构体声明
struct 
{
 char name[20];
 int age;
 float score;
}value[10],*p;

  这样的声明省略掉了我们结构体的名字,直接就创建了我们的变量。

  那么这样做编译器会不会报错呢?

  答案:不会报错

警告:

  **编译器会把上面的两个声明当成完全不同的两个类型,所以是非法的。

  匿名的结构体类型,如果没有对结构体类型重命名的话,基本上只能使用一次。**

结构体类型的自引用:

  学到数据结构的时候我们就会知道链表这个概念。

  就又没有想过,结构体里面包含结构体,一个连接着一个,形成一个链条一样的链表。

举例:

代码语言:c
复制
//就像这样写
struct Node
{
 int a;
 struct Node*next;
};

  以上就是我们的结构体的创建和初始化以及特殊的结构体声明定义。


3. 结构体内存大小

  那么结构体的内存大小又是怎么算的呢?

  接下来我们来学习一下。

代码语言:c
复制
struct stu
{
 char name[20];
 int age;
};

这个结构体内存大小多大呢?

答案:24

  为什么是24呢?我们就要了解最大对齐数这个概念。

对其规则

最大对齐数:

  **结构体的第1个成员对齐到和结构体变量起始位置偏移量为0的地址处。

  从第2个成员变量开始,都要对齐到某个对其数的整数倍的地址处,(对其数 = 编译器默认的⼀个对其数与该成员变量大小的较小值。)

  结构体总大小为最大对齐数的整数倍。

  嵌套了结构体的情况下,嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处,结构

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

举例:

注意:每一个编译器默认的对齐数都是不一样的,就像我们Vs这个编译器默认的对齐数为:8

代码语言:c
复制
#include<stdio.h>
struct S1
{
 char c1;//对齐数位1
 int i;//对齐数为4
 char c2;//对齐数为1
};
int main()
{
 printf("%zu\n", sizeof(struct S1));//选择最大对齐数的整数倍
 return 0;
}
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
修改默认对齐数
代码语言:c
复制
#include<stdio.h>
#pragam pack(1);//设置默认对齐数为1
struct S
{
 char c1;//对齐数位1,而我们默认对齐数为1 , 对齐数为1 
 int i;//对齐数为4,而我们默认对齐数为1 , 对齐数为1 
 char c2;//对齐数为1,而我们默认对齐数为1 , 对齐数为1 
};
#pragma pack();取消修改默认对齐数
int main()
{
printf("%d\n", sizeof(struct S));
 return 0;
}
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  得到的结果都是我们的1000。这样我们就能知道:结构体传参的时候,要传结构体的地址


4.结构体的传参

  结构体又是怎么传参的呢?

代码语言:c
复制
#include<stdio.h>
struct S
{
 int data[1000];
 int num;
};

//结构体传参

//测试传结构体
void test1(struct S s)
{
 printf("%d\n", s.num);
}

//测试地址
void test2(struct S* s)
{
 printf("%d\n", s->num);
}
int main()
{
 struct S s = {{1,2,3,4}, 1000};
 test1(s);//传结构体
 test2(&s);//传地址
 return 0;
}
在这里插入图片描述
在这里插入图片描述

  得到的结果都是我们的1000。这样我们就能知道:结构体传参的时候,要传结构体的地址


5.位段

  什么是位段?

  位段:

  **1. 位段的成员必须是int、unsigned int 或signed int ,在C99中位段成员的类型也可以选择其他整型家族类型,比如:char。

  2. 位段的成员名后边有⼀个冒号和⼀个数字。**

举例:

代码语言:c
复制
struct A
{
int _a:2;
int _b:3;
int _c:30;
};
int main()
{
 printf("%d\n", sizeof(struct A));
 return 0;
 }
在这里插入图片描述
在这里插入图片描述

这就是我们位段的写法。

A就是⼀个位段类型。

位段的内存分配:

  **1. 位段的成员可以是int、 unsigned int、signed int 或者是char 等类型

  2.位段的空间上是按照需要4个字节或者一个字节的方式开辟

  3.位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。**

例如:

代码语言:c
复制
#include<stdio.h>
struct S
{
char a:3;
char b:4;
char c:5;
char d:4;
};
int main()
{
 struct S s = {0};
 s.a = 10;
 s.b = 12;
 s.c = 3;
 s.d = 4;
 return 0;
}
在这里插入图片描述
在这里插入图片描述

**注意:

  位段在跨平台的时候会出现问题。

问题:

   int 这个位段被别的编译器当成有符号数还是无符号数是不确定的。

  位段中最大位的数不能确定。

  位段中的成员在内存中从左向右分配,还是从右向左分配

   当⼀个结构包含两个位段,第⼆个位段成员⽐较⼤,无法容纳于第⼀个位段剩余的位时,是舍弃

剩余的位还是利用,这是不确定的。

  总结:位段可以达到结构体那样的效果,并且可以很好的节省空间,但是有跨平台的问题存在。**


                                            完!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 1. 结构体类型声明定义
  • 2. 结构体的创建和初始化
    • 结构体的打印:
    • 结构的特殊声明:
    • 结构体类型的自引用:
  • 3. 结构体内存大小
    • 最大对齐数:
    • 修改默认对齐数
  • 4.结构体的传参
  • 5.位段
    • 位段的内存分配:
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档