c语言结构体与共用体

news2024/10/7 4:29:55

前面我们介绍了基本的数据类型 在c语言中 有一种特殊的数据类型 由程序员来定义类型

目录

一结构体

1.1概述

1.2定义结构体

1.3 结构体变量的初始化

1.4 访问结构体的成员

1.5结构体作为函数的参数

1.6指向结构的指针

1.7结构体大小的计算

二共用体

2.1概述

2.2 访问共用体成员


一结构体

1.1概述

结构是 C 编程中另一种用户自定义的可用的数据类型,它允许您存储不同类型的数据项

1.2定义结构体

结构体定义由关键字 struct 和结构体名组成,结构体名可以根据需要自行定义。

struct 语句定义了一个包含多个成员的新的数据类型,struct 语句的格式如下

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

tag 是结构体标签。

member-list 是标准的变量定义,比如 int i; 或者 float f;,或者其他有效的变量定义。

variable-list 结构变量,定义在结构的末尾,最后一个分号之前,您可以指定一个或多个结构变量

struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
} book;

我们来分析每一条语句 首先先是struct关键字标志着 我们要定义一个结构体 Books 是这个结构体的标签 这里可以通俗的理解为是我们用户自定义的一个数据类型 类型名是Books 和int类型类似 一个是官方定义的基本数据类型 一个是我们程序员自己定义的

{}里面的是结构体成员 对结构体成员这里没有任何要求 可以是基本数据类型 可以是指针 也可以是结构体类型

book 是这个结构体变量的名字

还有以下三种用法:

//此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c
//同时又声明了结构体变量s1
//这个结构体并没有标明其标签
struct 
{
    int a;
    char b;
    double c;
} s1;

//此声明声明了拥有3个成员的结构体,分别为整型的a,字符型的b和双精度的c
//结构体的标签被命名为SIMPLE,没有声明变量
struct SIMPLE
{
    int a;
    char b;
    double c;
};
//用SIMPLE标签的结构体,另外声明了变量t1、t2、t3
struct SIMPLE t1, t2[20], *t3;

//也可以用typedef创建新类型
typedef struct
{
    int a;
    char b;
    double c; 
} Simple2;
//现在可以用Simple2作为类型声明新的结构体变量
Simple2 u1, u2[20], *u3;

首先看第一种 没有声明标签,我们只声明了结构体变量s1

2:声明了标签但是没有声明变量 我们可以后续定义SIMPLE类型的变量

3:用typedef 声明一个新的数据类型 是Simple2

1.3 结构体变量的初始化

和其它类型变量一样,对结构体变量可以在定义时指定初始值

示例:结合上面说的三种定义 我们分别对应三种初始化

结构体变量初始化就是对里面的成员进行初始化

1 示例:

#include <stdio.h>
int main ()
{
   struct name 
   {
      char a[4];
      int num;
   }s1={{'p','d','x'},1};
   printf("%s\n",s1.a);
   printf("%d\n",s1.num);
   return 0;
}

2 示例:

#include <stdio.h>
int main ()
{
   struct
   {
      char a[4];
      int num;
   }s1={{'p','d','x'},1};
   printf("%s\n",s1.a);
   printf("%d\n",s1.num);
   return 0;
}

3 示例:

#include <stdio.h>
int main ()
{
   struct SIMPLE
   {
      char a[4];
      int num;
   };
  struct SIMPLE s1={{'p','d','x'},1};
   printf("%s\n",s1.a);
   printf("%d\n",s1.num);
   return 0;
}

4示例:

#include <stdio.h>
int main ()
{
   typedef struct
   {
      char name[4];
      int num;
   }m;
   m man={{'p','d','x'},1};
   printf("%d\n",man.num);
   return 0;
}

我们可以看到第一种 是最方便理解的,剩下的三种也可以完成定义和初始化 大家遇到了也需要知道分别对应的意思 

1.4 访问结构体的成员

为了访问结构的成员,我们使用成员访问运算符(.)

示例:
 

#include <stdio.h>
#include <string.h>
 
struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
};
 
int main( )
{
   struct Books Book1;        /* 声明 Book1,类型为 Books */
   struct Books Book2;        /* 声明 Book2,类型为 Books */
 
   /* Book1 详述 */
   strcpy( Book1.title, "C Programming");
   strcpy( Book1.author, "Nuha Ali"); 
   strcpy( Book1.subject, "C Programming Tutorial");
   Book1.book_id = 6495407;

   /* Book2 详述 */
   strcpy( Book2.title, "Telecom Billing");
   strcpy( Book2.author, "Zara Ali");
   strcpy( Book2.subject, "Telecom Billing Tutorial");
   Book2.book_id = 6495700;
 
   /* 输出 Book1 信息 */
   printf( "Book 1 title : %s\n", Book1.title);
   printf( "Book 1 author : %s\n", Book1.author);
   printf( "Book 1 subject : %s\n", Book1.subject);
   printf( "Book 1 book_id : %d\n", Book1.book_id);

   /* 输出 Book2 信息 */
   printf( "Book 2 title : %s\n", Book2.title);
   printf( "Book 2 author : %s\n", Book2.author);
   printf( "Book 2 subject : %s\n", Book2.subject);
   printf( "Book 2 book_id : %d\n", Book2.book_id);

   return 0;
}

1.5结构体作为函数的参数

概述:把结构作为函数参数,传参方式与其他类型的变量或指针类似

示例:在这里我们用到了结构体book1和book2作为函数的参数

#include <stdio.h>
#include <string.h>

struct Books
{
   char title[50];
};
void printbook(struct Books book)
{
  printf( "Book title : %s\n", book.title);

}
int main()
{
   struct Books book1;
   struct Books book2;
   strcpy( book1.title, "C Programming");
   strcpy( book2.title, "Telecom Billing");
   printbook( book1 );
   printbook( book2 );
}

运行结果:

1.6指向结构的指针

概述:可以定义指向结构的指针,方式与定义指向其他类型变量的指针相似

示例:指针的类型 是由指针指向对象的类型决定 

struct Books *struct_pointer;

可以在上述定义的指针变量中存储结构变量的地址。为了查找结构变量的地址,请把 & 运算符放在结构名称的前面,如下所示:

struct_pointer = &Book1;

使用指向该结构的指针访问结构的成员,必须使用 -> 运算符示例

struct_pointer->title;

示例:

#include <stdio.h>
#include <string.h>

struct Books
{
   char title[50];
};
void printbook(struct Books *book)
{
  printf( "Book title : %s\n", book->title);

}
int main()
{
   struct Books book1;
   strcpy( book1.title, "C Programming");
   printbook( &book1 );
}

1.7结构体大小的计算

概述:C 语言中,我们可以使用 sizeof 运算符来计算结构体的大小,sizeof 返回的是给定类型或变量的字节大小。

对于结构体,sizeof 将返回结构体的总字节数,包括所有成员变量的大小以及可能的填充字节

注意,结构体的大小可能会受到编译器的优化和对齐规则的影响,编译器可能会在结构体中插入一些额外的填充字节以对齐结构体的成员变量,以提高内存访问效率。因此,结构体的实际大小可能会大于成员变量大小的总和

我们来看示例了解:我们在上述结构体加了一个char类型的 应该占用1个字节的大小

输出应该是29 那对不对呢 我们来看一下运行结果

#include <stdio.h>
struct Person {
  char name[20];
  int age;
  float height;
  char a;
};

int main()
{
 struct Person person;
 printf("结构体 Person 大小为: %zu 字节\n", sizeof(person));
 return 0;
}

我们可以看到是32字节为什么呢?

这里是涉及到结构体自动补齐 在char虽然占用1字节,但是由于对齐规则 系统仍给了四个字节的空间大小

那什么是对齐规则呢?

结构体中成员变量分配的空间是按照成员变量中占用空间最大的来作为分配单位,同样成员变量的存储空间也是不能跨分配单位的,如果当前的空间不足,则会存储到下一个分配单位中 

上例代码中 我们最大的是int类型是4个字节 char name[20],占用了20个字节是int类型占用空间的整数倍 所以不需要对齐 char a;占用一个字节 自动对齐为4个字节

我们来看示例2:结构体只有char类型 占用空间最大的就是一个字节

#include <stdio.h>
struct Person {
  char name[20];
  char a;
};

int main()
{
 struct Person person;
 printf("结构体 Person 大小为: %zu 字节\n", sizeof(person));
 return 0;
}

所以 这里是不需要进行对齐的 占用空间就是21字节 

二共用体

2.1概述

概述:共用体是一种特殊的数据类型,允许您在相同的内存位置存储不同的数据类型。您可以定义一个带有多成员的共用体,但是任何时候只能有一个成员带有值。共用体提供了一种使用相同的内存位置的有效方式

是不是很迷糊 什么是相同的内存位置储存不同的数据类型,我们知道 不同的数据类型是占用了不同的内存空间 不同的变量是占用了不同的内存位置的 共用体是所有变量用同一内存位置 所以一次只能进行赋值一个变量 因为内存位置是有且只有一个

基本格式:

union [union tag]
{
   member definition;
   member definition;
   ...
   member definition;
} [one or more union variables];

union tag 是可选的,每个 member definition 是标准的变量定义,比如 int i; 或者 float f; 或者其他有效的变量定义。在共用体定义的末尾,最后一个分号之前,您可以指定一个或多个共用体变量,这是可选的 

示例:

union Data
{
   int i;
   float f;
   char  str[20];
} data;

现在,Data 类型的变量可以存储一个整数、一个浮点数,或者一个字符串。这意味着一个变量(相同的内存位置)可以存储多个多种类型的数据。可以根据需要在一个共用体内使用任何内置的或者用户自定义的数据类型。

共用体占用的内存应足够存储共用体中最大的成员。例如,在上面的实例中,Data 将占用 20 个字节的内存空间,因为在各个成员中,字符串所占用的空间是最大的。下面的实例将显示上面的共用体占用的总内存大小:

#include <stdio.h>
#include <string.h>
 
union Data
{
   int i;
   float f;
   char  str[20];
};
 
int main( )
{
   union Data data;        
 
   printf( "Memory size occupied by data : %ld\n", sizeof(data));
 
   return 0;
}

运行结果:

2.2 访问共用体成员

为了访问共用体的成员,我们使用成员访问运算符(.)。成员访问运算符是共用体变量名称和我们要访问的共用体成员之间的一个句号。您可以使用 union 关键字来定义共用体类型的变量。下面的实例演示了共用体的用法:

#include <stdio.h>
#include <string.h>
union Data
{
   int i;
   float f;
   char  str[20];
};
 
int main( )
{
   union Data data;        
   data.i=1;
   data.f=1.2;
   strcpy( data.str, "C Programming");
   printf( "data.i : %d\n", data.i);
   printf( "data.f : %f\n", data.f);
   printf( "data.str : %s\n", data.str);
   return 0;
}

运行结果:

我们可以看到其中 i和f的值被影响了 那为什么呢? 前面我们是共用体是共用一块内存位置的,同一时间 一块内存位置只能储存一个变量 所以在赋值其他变量的时候之前赋值的,就已经失去意义了

所以最后赋值的str 依旧是可以正常访问的

正确的应该是:

#include <stdio.h>
#include <string.h>
union Data
{
   int i;
   float f;
   char  str[20];
};
int main( )
{
   union Data data;        
 
   data.i = 10;
   printf( "data.i : %d\n", data.i);
   
   data.f = 220.5;
   printf( "data.f : %f\n", data.f);
   
   strcpy( data.str, "C Programming");
   printf( "data.str : %s\n", data.str);
 
   return 0;
}

 所有的成员都能完好输出,因为同一时间只用到一个成员。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1460225.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

网络编程知识整理

目录 1.1 引言 1.2 分层 1.3 TCP/IP的分层 1.4 互联网的地址 1.5 域名服务 1.6 封装 1.7 分用 1.8 端口号 1.1 引言 很多不同的厂家生产各种型号的计算机&#xff0c;它们运行完全不同的操作系统&#xff0c;但 T C P / I P协议族允许它们互相进行通信。这一点很让人感…

小红书家居种草商品笔记,需要注意哪些?

家居赛道一直都是小红书的强势赛道之一。那么如果想要成为一个家居博主&#xff0c;或者家居品牌想要入驻小红书&#xff0c;提升影响力&#xff0c;该如何进行推广呢?今天我们就从家居商品笔记的角度&#xff0c;和大家探讨下小红书家居种草商品笔记&#xff0c;需要注意哪些…

PHP分析二维数据表(长度|数字字段|空值|纯姓名|英文用户名|科学计数|是否等长|是否唯一)

先看图&#xff0c;后有完整代码 <?php $t "Excel数据转Sql查询系统字段半智能分析"; $s "Excel复制过来的二维结构表内容,分析查询条件&#xff01;"; $x "字段|最大长度|长度有|数字字段|空值存在|纯姓名|英文用户名|科学计数|是否等长|是否…

pandas DataFrame 导出到Excel格式美化

默认情况下&#xff0c;DataFrame 的 to_excel() 方法导出到 Excel 格式是比较丑的&#xff0c;本篇的代码演示了用一种比较简单的方法进行美化。要点&#xff1a; 使用 Excel 的 Table &#xff08;经常被称为超级表&#xff09;自动列宽 美化前&#xff0c;输出的格式如下&…

高级统计方法 第2次作业

概念 1. &#xff08;a&#xff09; 光滑度高的好&#xff0c;样本足够多光滑度越高就越能表征真实情况&#xff0c;也能对预测变量更好的预测。 &#xff08;b&#xff09; 光滑度低的好&#xff0c;因为可能“过拟合”&#xff0c;一些误差大的数可能会较大的影响到预测…

微信小程序video 点击自动全屏播放

//因为这个地址可能是图片也可能是视频 点击 图片可以预览&#xff0c;点击视频可放大全屏自动播放。 代码如下 <view v-else :class{contentImg: x.picture.length0} style"margin-top: 10px;"v-for"(x1, y1) in x.picture" :key"y"><…

【Docker】Linux主机部署Docker

Docker部署 1.二进制文件部署 到如下地址&#xff0c;下载二进制包。 Docker官网&#xff1a;https://docs.docker.com/engine/install/binaries/ 网易镜像源&#xff1a;https://mirrors.163.com/docker-ce/linux/static/stable/x86_64/ 下载好的二进制包上传到主机&#xf…

【LeetCode】递归精选8题——基础递归、链表递归

目录 基础递归问题&#xff1a; 1. 斐波那契数&#xff08;简单&#xff09; 1.1 递归求解 1.2 迭代求解 2. 爬楼梯&#xff08;简单&#xff09; 2.1 递归求解 2.2 迭代求解 3. 汉诺塔问题&#xff08;简单&#xff09; 3.1 递归求解 4. Pow(x, n)&#xff08;中等&…

(每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理第11章 项目成本管理(一)

博主2023年11月通过了信息系统项目管理的考试&#xff0c;考试过程中发现考试的内容全部是教材中的内容&#xff0c;非常符合我学习的思路&#xff0c;因此博主想通过该平台把自己学习过程中的经验和教材博主认为重要的知识点分享给大家&#xff0c;希望更多的人能够通过考试&a…

消息队列-RabbitMQ:workQueues—工作队列、消息应答机制、RabbitMQ 持久化、不公平分发(能者多劳)

4、Work Queues Work Queues— 工作队列 (又称任务队列) 的主要思想是避免立即执行资源密集型任务&#xff0c;而不得不等待它完成。我们把任务封装为消息并将其发送到队列&#xff0c;在后台运行的工作进程将弹出任务并最终执行作业。当有多个工作线程时&#xff0c;这些工作…

python51-Python流程控制if分支之不要随意缩进

需要说明的是,虽然Python 语法允许代码块随意缩进N个空格,但同一个代码块内的代码必须保持相同的缩进,不能一会缩进2个空格,一会缩进4个空格。例如如下代码。 上面程序中第二条print语句缩进了5个空格,在这样的情况下,Python解释器认为这条语句与前一条语句(缩进了4个空格…

用html编写的招聘简历

用html编写的招聘简历 相关代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</tit…

没有代码签名证书会怎么样?

随着Windows的SmartScreen功能的普及&#xff0c;如果一个软件发布的时候没有通过代码签名证书进行数字签名&#xff0c;那这个软件从发布&#xff0c;下载&#xff0c;安装&#xff0c;运行等&#xff0c;基本都会遭到系统的风险警告&#xff0c;运行拦截。其目的在于警示用户…

MapGIS 10.6 Pro前端开发低代码,快速构建WebGIS应用

随着实景三维、CIM、数字孪生等的快速发展&#xff0c;相关应用开发需求的市场增长对企业IT交付能力的要求越来越高&#xff0c;为了确保质量并实现提效降本&#xff0c;并让专业开发者更加专注于更具有价值和创新型的工作&#xff0c;低代码开发技术成为大家的优先选择。 为了…

工作入职必备:一寸照片尺寸要求及自拍换底色方法

踏入职场的第一步&#xff0c;往往从一张小小的一寸照片开始。这张看似不起眼的照片&#xff0c;却是你给新同事、新领导的第一印象。今天&#xff0c;我们就来深入探讨一寸照片的尺寸要求&#xff0c;以及如何巧妙地通过自拍来更换背景颜色&#xff0c;让你的入职照片既专业又…

【Java EE初阶二十一】关于http(二)

2. 深入学习http 2.5 关于referer Referer 描述了当前页面是从哪个页面跳转来的&#xff0c;如果是直接在地址栏输入 url(或者点击收藏夹中的按钮) 都是没有 Referer。如下图所示&#xff1a; HTTP 最大的问题在于"明文传输”,明文传输就容易被第三方获取并篡改. …

我国为分散染料(分散性染料)生产及出口大国 合成纤维领域为其主要需求端

我国为分散染料&#xff08;分散性染料&#xff09;生产及出口大国 合成纤维领域为其主要需求端 分散染料又称分散性染料&#xff0c;指分子结构中不含水溶性基团的染料。与其他染料相比&#xff0c;分散染料具有耐光性好、色彩饱和度高、易于分散、绿色环保等优势&#xff0c;…

探索未来-Sora

AI如何将静态图像转化为动态、逼真的视频&#xff1f; OpenAI 的 Sora 通过时空片段&#xff08;以下统称片段&#xff09;的创新使用给出了答案。 Sora 展示与探讨 在快速发展的生成模型领域&#xff0c;OpenAI 的 Sora成为一个重要的里程碑&#xff0c;有望重塑我们对视频生…

Python编程实验四:函数的使用

目录 一、实验目的与要求 二、实验内容 三、主要程序清单和程序运行结果 第1题 第2题 第3题 第4题 第5题 四、实验结果分析与体会 一、实验目的与要求 &#xff08;1&#xff09;通过本次实验&#xff0c;学生应掌握函数的定义与调用的基本语法&#xff0c;能根据需要…

K8S的架构(1)

目录 一.k8s K8S有 master 和 worker node 两类节点&#xff1a; ​编辑 二.K8S创建Pod资源的工作流程 三.K8S资源对象 Pod&#xff1a;是K8S能够创建和管理的最小单位。 Pod控制器: 四.K8S资源配置信息 一.k8s kubernetes &#xff1a; Google旗下的容器跨主机编排…