C语言-结构类型

程序中的数据都需要有类型支撑,当数据很复杂时(不是简单的一个值,如时间信息:年月日时分秒6个数据需要作为一个整体),我们需要声明一个新的结构类型来描述这种复合的数据(可以包含很多不同类型的成员),然后我们可以用这个结构的一个变量来表达复合的数据。(有点类似java的类)

1. 结构体声明与结构变量定义

可参考:
https://www.runoob.com/cprogramming/c-structures.html
https://www.runoob.com/cprogramming/c-typedef.html

我的学习笔记:

声明在函数内/外的规则和本地变量一样一般在函数外声明结构类型,这样可以被多个函数使用。
声明好后,千万别忘记{}后加上;

声明结构体的形式(可以在struct前加typedef关键字重定义类型)并定义可以使用的变量 —— 3种方式

t1和t2都是time结构类型的变量:

同时做了声明和定义(main并列 全局):

如下,t1和t2是无名结构变量(程序只需要用到少量确定的结构变量)

结构变量的初始化

集成初始化只能在定义时同步做,定义好后不支持这样初始化了,但可以强制类型转换重新赋值。【如果结构中还有数组,数组的初始化需要集成初始化时一并做好或者for/while循环,再或者逐个赋值】

对结构赋值:

struct time {int year;int month;int date;int hour;int min;int sec;
} t1, t2;t1 = (struct time){2023,02,02,16, .sec=55};t2 = t1;t2.year = 2022;printf("#t1 = %i-%i-%i %i:%i:%i#\n",t1.year, t1.month, t1.date, t1.hour, t1.min, t1.sec);printf("#t2 = %i-%i-%i %i:%i:%i#\n",t2.year, t2.month, t2.date, t2.hour, t2.min, t2.sec);

关于C语言 结构体和数组 的说明:
结构变量初始化和数组类似,顺次赋值、缺省默认0等;
但是,1. 数组单元必须同类型,结构体成员可以不同类型;2. 数组访问单元用[],结构体访问成员用. ,访问一个结构直接用结构变量名;3. 结构变量相互可以直接做赋值、取地址等运算(结构变量名不代表地址-需要结构指针 取地址&)。

2. 结构作为函数参数(返回指针 无限套娃)

首先,scanf接收和printf输出结构体都无法一次性对结构变量整体操作,只能对一个一个成员操作,如果每次都要写很多这种输入输出太麻烦了,我们一般写两个函数来操作。
然而注意当结构变量直接传入函数时,和数组和指针不同,传入的是拷贝值。基础的解决方案如下:结构类型的函数中定义临时结构变量回传给调用者(两个结构变量可以相互直接赋值) ——



但这种操作既费时间又费空间,我们更好的办法使用结构指针完成这个功能 ——
参考下面这个案例(明天的日期是?)
【( * p).mon = 12; 等价于 p -> mon = 12;】

#include "test1.h"/*
* ***程序入口 Main Empty项目***
*/
int main(int argc, char const *argv[])
{struct date tomorrow;struct date *p = &today;printf("Enter today's date(yyyy mm dd):");//scanf("%i %i %i", &today.year, &today.mon, &today.day);output(*inputDate(p)); //无限套娃 可以做很多有趣的表达式if ( today.day != numberOfDays(today) ) {tomorrow.day = today.day + 1;tomorrow.mon = today.mon;tomorrow.year = today.year;}else if ( today.mon == 12 ) {tomorrow.day = 1;tomorrow.mon = 1;tomorrow.year = today.year + 1;}else {tomorrow.day = 1;tomorrow.mon = today.mon + 1;tomorrow.year = today.year;}printf("And Tomorrow is:");output(tomorrow);return 0;
}#include "test1.h"//结构体参数函数
bool isLeap(struct date d) { //C99bool leap = false;if ((d.year % 4 == 0 && d.year % 100 != 0) || d.year % 400 == 0) {leap = true;}return leap;
}
int numberOfDays(struct date d) {int day; //每月月底const int daysPerMonth[12] = {31,28,31,30,31,30,31,31,30,31,30,31};if (d.mon == 2 && isLeap(d)) {day = 29;}else {day = daysPerMonth[d.mon-1];}return day;
}
struct date * inputDate(struct date *p) {scanf("%d %d %d", &p->year, &p->mon, &p->day); //p->year等价于(*p).yearreturn p;
}
void output(struct date d) {printf("%i-%i-%i.\n", //%i和%d类似,但%i可以区分八进制和十六进制 printf中通用d.year, d.mon, d.day);
}#ifndef _TEST1_H //定义预处理变量,使用大写文件名 实际可以随意命名(不重复)
#define _TEST1_H#include <stdio.h>
#include <stdbool.h>struct date {int year;int mon;int day;
} today;bool isLeap(struct date d);
int numberOfDays(struct date d);
struct date * inputDate(struct date *p);
void output(struct date d);#endif




3. 结构数组( 初始化{{}} )

#include <stdio.h>typedef struct student {char stuID[10]; //学号char name[10]; //姓名int age; //年龄int gender; //性别 male1 female0char major[20]; //学科专业double grade_point; //学分绩点 0~5
} Stu;int main() {Stu stuForm[] = {{ "20200101", "小明", 23, 1, "计算机科学", 3.89 }, { "20200215", "小红", 23, 0, "软件工程", 3.56 }, { "20180437", "小军", 25, 1, "大数据", 3.45 }, { "20191403", "小芳", 24, 0, "数字媒体技术", 3.67 }, };int i;for ( i = 0; i < sizeof(stuForm)/sizeof(stuForm[0]); i ++ ) {printf("%d: %s %s %d %d %s %4.2f\n", //%4.2f 宽度4中小数点占1i+1, stuForm[i].stuID, stuForm[i].name, stuForm[i].age, stuForm[i].gender, stuForm[i].major, stuForm[i].grade_point);}return 0;
}

#include <stdio.h>#define int long longtypedef long long ll;struct point{int x;int y;
};
struct rectangle {struct point pt1; //不是指针,是变量struct point pt2;
};void printRect(struct rectangle r);signed main() {int i;struct rectangle rects[2] = {{{1,2}, {3,4}}, {{5,6}, {7,8}} }; //2 rectanglesfor ( i = 0; i < 2; i ++ ) {printRect(rects[i]);}//   struct rectangle r, *rp;
//  rp = &r;
//  r.pt1.x //rp->pt1.x  (r.pt1).x  (rp->pt1).x
//  r.pt2.yreturn 0;
}void printRect(struct rectangle r) {printf("<%lld,%lld> to <%lld,%lld>\n", r.pt1.x, r.pt1.y, r.pt2.x, r.pt2.y);
}

构中构:数组里是结构,结构里有数组,结构里有结构,结构的数组里是结构……

4. 联合 typedef union

typedef   已有类型的名字   重新定义的简化名字;
用途:改善了程序可读性

union 类似于 struct ,区别在于 union 的成员变量共用同一份空间(大小最大的成员)【在同一时间内只有一个成员是有效的】
union的使用场景:得到一个类型内部字节,对文件操作中常用

#include <stdio.h>typedef union {int i;char ch[sizeof(int)];
} CHI;int main() {CHI chi;int i;chi.i = 1234; //0x04D2for ( i = 0; i < sizeof(int); i ++ ) {printf("%02hhX", chi.ch[i]);//(X)显示16进制数的一种方式:位数不足自动补0,hh表示就是一个字节不扩展,显示2个16进制数字}putchar(10);return 0;
}

x86CPU是一种小端机器,小端序( 数据 低位在前)

大端:数据低位保存在内存地址高位,数据高位保存在地址低位【地址从小到大递增,数据从高位排到低位】
小端:数据的低位保存在内存的低地址中,而数据的高位保存在内存的高地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低,和我们的逻辑方法一致。

C语言学习笔记11-结构体(struct、结构作为函数参数、结构数组)、联合体/共用体typedef; union(大、小端序)相关推荐

  1. C语言学习笔记(1)--基本概念和函数用法

    最近开始重新学习C语言,所谓"好记性不如烂笔头",把一些要记住的基本概念和一些函数用法,无论是书上看到的,或者是在别人的博客和论坛上帖子看到的,都归纳到这篇文章中: 2014-10 ...

  2. C语言学习笔记06-占位符格式、C基本类型及逃逸字符一些细节(附介绍BCD码)

    主要整理有关占位符格式与逃逸字符的一些细节 朋友们,看栗子--"BCD解码" (文末附BCD码介绍) 一个BCD数的十六进制是0x12(对应二进制表示:0001 0010),它表达 ...

  3. c语言学习笔记【结构体02】结构体指针变量与结构体变量的函数参数,C语言学习笔记结构体02结构体指针变量与结构体变量的函数参数.docx...

    C 语言学习笔记[结构体02]结构体指针变量与结构体变量 的函数参数 C 语言学习笔记之结构体指针变量一提指针,那可 是 C 语言的核心了,有多少学子曾拜倒在指针的脚下.单纯的说指针,其实并不难,但是 ...

  4. c语言如何宏定义枚举型结构体,C语言学习笔记--枚举结构体

    枚举 枚举是一种用户定义的数据类型,它用关键字enum以如下语法格式来声明: enum 枚举类型名字 {名字0,名字1,...,名字n}: 枚举类型名字通常并不真的使用,要用的是大括号里面的名字,因为 ...

  5. C语言学习笔记之动态内存分配结构体——辣鸡版学生管理系统

    @[C语言学习笔记] 小辣鸡自学C语言中,好多视频教程都有这个案例,小辣鸡自己边学边记,下边是代码. 如有错误,感谢告知!!! #include<stdio.h> #include< ...

  6. Lawliet|C语言学习笔记5——循环结构

    C语言学习笔记--循环结构 1.求1+2+3+-+100 #include<stdio.h> int main() {int i=1,sum=0; //定义变量i的初值为1,sum的初值为 ...

  7. Lawliet|C语言学习笔记3——顺序结构

    C语言学习笔记--顺序结构 计算a+b #include<stdio.h> int main() {int a,b,sum;scanf("%d%d",&a,&a ...

  8. Lawliet|C语言学习笔记4——选择结构

    C语言学习笔记--选择结构 求一元二次方程的根 简约版 #include<stdio.h> #include<math.h> //程序中要调用求平方根函数sqrt int ma ...

  9. go get 拉取指定版本_go语言学习笔记-基础知识-3

    相关文档 go语言学习笔记-目录 1.简介 1.1 什么是GO Go 是一个开源的编程语言,它能让构造简单.可靠且高效的软件变得容易.Go是从2007年末由Robert Griesemer, Rob ...

最新文章

  1. 这就是奇客文化?简直太有才了!
  2. MySQL下备份和恢复简单介绍
  3. java矩形碰撞检测_旋转矩形的Java碰撞检测?
  4. tensorrt 低精度推理
  5. UML-2-迭代、进化和敏捷
  6. Shell编程之变量赋值和引用
  7. 在 .NET Core 3.0 中实现 JIT 编译的 JSON 序列化,及一些心得与随想
  8. C/C++后端-服务端开发技术博文分类汇总
  9. 清空VS2003/VS2005最近打开解决方案记录
  10. iPhone 12系列终于将配高刷屏:120Hz恐怕还得等两年
  11. linux怎么创建牡蛎_Linux文件也有快捷方式?有的,你会用吗?
  12. ubuntu下vlc-android编译
  13. js去掉字符串的空格
  14. java我行我素购物系统_用java怎么编写 我行我素shopping购物管理体统
  15. 【错误解决】Ubuntu20.04安装输入法遇到的问题
  16. ML面试1000题系列(71-80)
  17. 主流HTML5游戏开发引擎的分析和对比
  18. SSL-ZYC 2405 巧克力
  19. proxmox的安装
  20. 手动搭建一个https服务器,并颁发证书

热门文章

  1. yota3墨水屏调节对比度_【YotaPhoneYOTA3评测】屏幕:背面墨水屏玩法太多样_YotaPhone YOTA 3_手机评测-中关村在线...
  2. 手机sd卡清除扣扣邮箱图片文件怎么恢复
  3. java redis 发送短信验证码
  4. Ubuntu登陆不进去的一个原因
  5. 平衡二叉树(AVL)的左旋和右旋
  6. C语言——逆序乘积式
  7. 计算两个矩阵乘积(两种方式实现)(C语言)
  8. 桌面上ie图标不见了,怎样恢复
  9. vue element计算表格合计问题
  10. vue 页面保留缓存和清除缓存