C语言中自定义数据类型

文章目录

  • C语言中自定义数据类型
  • 枚举类型
  • 结构体类型
  • 复数类型

C语言中自定义数据类型

枚举类型

  • 形式:
    声明:enum 枚举类型名 { 枚举符列表, }枚举变量名;
    使用:enum 枚举类型名 枚举变量名 = 枚举符;
    • 枚举变量占4字节与int相同,存储方式相同,在cpu看来就是一个int型变量。
    • 枚举常量则是在编译的时候确定其值,#define宏常量是在预编译阶段进行简单替换。

  • 常规的枚举变量 (enum MY_enum color)
#include <stdio.h>enum MY_enum {red,green = 3,blue
};int main() {enum MY_enum color = red;printf("%d", color);return 0;
}
  • 匿名枚举变量 (color)
#include <stdio.h>enum {red,green,blue
} color;int main() {color = red;printf("%d", color);return 0;
}
  • 一些约束

    • 不推荐直接对其进行加减等运算。
    • 建议不要随便赋给枚举变量枚举符之外的值,赋值时会进行隐式类型转换与int类型一致。
    • 如果出现与enum的枚举符同名的变量,在之后的程序中都将按新的变量进行,不要使用枚举符同名的变量,有的编译器甚至不报错!
#include <stdio.h>
enum MY_enum{red,green,blue
};int main() {enum MY_enum color = blue;printf("%d / %d / %d \n",blue , color, sizeof(color));// color占4字节跟int一样int red = 0x05;    color = red;printf("%d", color);// 这里color的值变为0x05enum MY_enum* penum = &color;printf("%d", *penum);return 0;
}



结构体类型

  • 形式
    声明:‘struct 结构体类型名 {结构体声明列表;} 结构体变量名;’
    使用: ‘struct 结构体类名 结构体变量名 = {,,};’
#include <stdio.h>struct PointType
{int x;int y;
} point1 = {1,2};int main() {struct PointType point2 = {.x = 20};struct PointType* p = &point1;printf("%d / %d", p->x, p->y);return 0;
}

{,}为初始化器(initializer),可用.的方式赋值及指定成员的初始化器(designated initializer)
结构体复合字面量(structural compund literal)

对于结构体变量用.的方式引出
对于结构体指针用->的方式引出

  • 位域(bit fields)
    • 形式:‘类型 标识符 : 位宽;’
    • 约束:
  1. 不能对位域成员做取地址操作(在某些情况下会触发hard fault)
  2. 位域成员不能用sizeof
  3. 不能用对齐属性来修饰位域
  4. 位宽不能超出该类型的大小
#include <stdio.h>
#include <stdint.h>enum MYenum {ENUM1,ENUM2,ENUM3
};int main() {struct BitField {uint32_t a : 6;// uint8_t b : 12; warring:invalid size for bit field// _Alignas(int32_t) int32_t a : 5; warring:attribute "_Alignas" does not apply to bit fieldsuint16_t b : sizeof(ENUM1);  // uint16_t b : 4;enum MYenum e : ENUM3; // enum MYenum e : 2;}bf1 = {10,20}, bf2 = {.a = 10, .e = ENUM3};return 0;
}

  • 位域的存储

    • 两相互毗邻的位域成员,若第一个成员仍有足够的存储空间,则第二个位域成员会与第一个
      成员打包在一起
    • 为了满足字节对齐,需在某些位域变量间补零
    • 一个单元内的位域分配次序从高位到低位还是从低位到高位由具体实现决定
  •          e  y  x      c               b      a(0) 10 1 0000 011101111(00000)01010 011000  高位  <-------------------------------> 低位
    
#include <stdio.h> 
#include <stdint.h>
#include <stdbool.h>int main() {enum MyEnum {ENUM1,ENUM2,ENUM3};struct MyStruct {int32_t a : 6;int16_t b : 5;int8_t c : 8;char x : 4;bool y : 1;enum MyEnum e : 2;}s = {0x18,0x0a,0x77,'\0',true,ENUM3};// s 的二进制表示为//      e  y  x      c               b      a// (0) 10 1 0000 011101111(00000)01010 011000//  高位  <-------------------------------> 低位return 0;
}

如果你使用了符合字面量(compound literal)赋值,gcc编译器会直接将函数内的普通结构体变量升级为global或static一样的变量(即拥有全局作用域或者静态生存期)来赋值

.LC0:.byte   152.byte   2.byte   119.byte   80main:mov     eax, DWORD PTR .LC0[rip]mov     DWORD PTR [rbp-8], eax

对于单独对每个结构体变量赋值的操作就会相当麻烦,因为涉及存储时的字节对齐等,需要一堆移位和与或的运算。例如:

        movzx   eax, BYTE PTR [rbp-8]and     eax, -64or      eax, 24mov     BYTE PTR [rbp-8], almovzx   eax, WORD PTR [rbp-8]and     ax, -1985or      ax, 640mov     WORD PTR [rbp-8], axmov     BYTE PTR [rbp-6], 119movzx   eax, BYTE PTR [rbp-5]and     eax, -16mov     BYTE PTR [rbp-5], almovzx   eax, BYTE PTR [rbp-5]or      eax, 16mov     BYTE PTR [rbp-5], almovzx   eax, BYTE PTR [rbp-5]and     eax, -97or      eax, 64mov     BYTE PTR [rbp-5], al;MOVZX — Move With Zero-Extend;MOVSX/MOVSXD — Move With Sign-Extension
  • 字节对齐与字节填充

一般会进行4字节对齐,即变量的起始地址一定是4字节的倍数。

  • _Alignof和_Alignas操作符

_Alignof(表达式)返回表达式所占的字节数
_Alignas()用户自定义该变量的字节对齐方式可以为(0,1,2,4,8,12,4的整数倍)

#include <stdio.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdalign.h>
int main() {size_t size = _Alignof(max_align_t);printf("%zu \n", size);size = alignof(bool);printf("%zu \n", size);return 0;
}
  • 结构体成员的字节对齐和字节填充
  1. 结构体第一个成员所在的偏移地址为0。
  2. 每个成员根据其类型或程序员指定对其字节数来判定偏移地址,如果无法堆积,则在两个成员之间补0,直至其地址可以对齐。
  3. 结构体对象的字节对齐要求与其成员中最大字节对齐要求相一致。
  4. 结构体对象的大小为其对齐字节数的倍数
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdalign.h>int main() {struct {int8_t a;int32_t b;int16_t c;int64_t d;} s = {0x01,0x02,0x03,0x04};return 0;
/*a               b        c                               d     
|  |        |           |     |                 |                       |10 00 00 00 20 00 00 00 30 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00
*/
}



复数类型

#include <complex.h>这个头文件之后便可使用复数类型。
但是谁会真的这样用捏,毕竟很多运行环境并不支持这么做

#include <stdio.h> 
#include <stdint.h>
#include <stdbool.h>
#include <complex.h>int main() {float complex comp = 2.5f + 1.5f;comp += 3.0f * I;float r = crealf(comp);float i = cimagf(comp);long double complex comp2 = {1.2f, 2.5f};return 0;
}







                                     ------ By Flier

2024.1.25

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

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

相关文章

课堂秩序要求有哪些内容

你是否曾经疑惑&#xff0c;为什么有些课堂总是秩序井然&#xff0c;而有些则混乱不堪&#xff1f;作为一位经验丰富的老师&#xff0c;我想告诉你&#xff0c;课堂秩序不仅仅是学生安静听讲那么简单&#xff0c;它背后涉及到许多关键因素&#xff0c;直接影响着教学质量和学习…

postgresql 手动清理wal日志的101个坑

新年的第一天&#xff0c;总结下去年遇到的关于WAL日志清理的101个坑&#xff0c;以及如何相对安全地进行清理。前面是关于WAL日志堆积的原因分析&#xff0c;清理相关可以直接看第三部分。 首先说明&#xff0c;手动清理wal日志是一个高风险的操作&#xff0c;尤其对于带主从的…

蓝桥杯刷题--python-4

0成绩分析 - 蓝桥云课 (lanqiao.cn) import os import sys # 请在此输入您的代码 n=int(input()) max_=float(-inf) min_=float(inf) res=0 for _ in range(n): score=int(input()) # 最高分 max_=max(max_,score) # 最低分 min_=min(min_,score) # 总分 res+=sc…

工业视觉发展历程解析

工业视觉发展历程解析 工业视觉发展历程解析引言工业视觉的起源与初期发展1.1 定义与最初应用1.2 早期的视觉检测技术1.3 计算机视觉的引入和应用1.3 计算机视觉的引入和应用 光学与影像处理技术的进步2.1 光学技术的演进2.2 影像处理算法的发展2.3 早期系统的局限性 工业视觉系…

CleanMyMac X 4.14.7帮您安全清理Mac系统垃圾

CleanMyMac X 4.14.7是一款强大的 Mac 清理、加速工具和健康卫士,可以让您的 Mac 再次恢复巅峰性能。 移除大型和旧文件、卸载应用,并删除浪费磁盘空间的无用数据。 5倍 更多可用磁盘空间 CleanMyMac X 4.14.7帮您安全清理Mac系统垃圾 CleanMyMac X 4.14.7一键深度扫描mac系统…

Java常用类与基础API--String的理解与不可变性

文章目录 一、字符串相关类之不可变字符序列&#xff1a;String&#xff08;1&#xff09;对String类的理解(以JDK8为例说明)1、环境2、类的声明3、内部声明的属性 &#xff08;2&#xff09;String的特性&#xff08;3&#xff09;字符串常量的存储位置1、举例2、String的存储…

「优选算法刷题」:数青蛙

一、题目 给你一个字符串 croakOfFrogs&#xff0c;它表示不同青蛙发出的蛙鸣声&#xff08;字符串 "croak" &#xff09;的组合。由于同一时间可以有多只青蛙呱呱作响&#xff0c;所以 croakOfFrogs 中会混合多个 “croak” 。 请你返回模拟字符串中所有蛙鸣所需不…

LeetCode跳跃游戏 VI

题目描述 给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。 一开始你在下标 0 处。每一步&#xff0c;你最多可以往前跳 k 步&#xff0c;但你不能跳出数组的边界。也就是说&#xff0c;你可以从下标 i 跳到 [i 1&#xff0c; min(n - 1, i k)] 包含 两个端点的任意位…

技术精英求职必备:全栈开发工程师简历制作全指南

简历编写核心原则 撰写针对全栈开发工程师职位的简历时&#xff0c;关键在于准确展现您在前端和后端开发方面的综合技能、项目经验和技术成就。简历应作为您展示跨多个技术栈的编程能力、构建完整应用解决方案和有效解决全栈技术问题的能力的窗口。确保每一项经历和技能都紧密…

Python OCR 之旅:PaddleOCR 与 pytesseract 比较及应用

简介&#xff1a; 在 Python 技术栈中&#xff0c;光学字符识别&#xff08;OCR&#xff09;是一个非常实用的功能&#xff0c;它可以将图片中的文本内容提取出来。在这篇文章中&#xff0c;我们将比较两个常用的 OCR 库&#xff1a;PaddleOCR 和 pytesseract&#xff0c;了解…

Day39- 动态规划part07

一、爬楼梯 题目一&#xff1a;57. 爬楼梯 57. 爬楼梯&#xff08;第八期模拟笔试&#xff09; 题目描述 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬至多m (1 < m < n)个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 注意&#xff1a;…

作业2.11

1、选择题 1.1、若有以下程序 main() { char a1,b2; printf("%c,",b); printf("%d\n",b-a); } 程序运行后的输出结果是 C A&#xff09;3,2 B&#xff09;50,2 C&#xff09;2,2 D&#xff09;2,50 1.2、有以下程序 main() { int a,b,d25; a…

MATLAB算法实战应用案例精讲-【图像处理】相机标定(基础篇)(二)

目录 算法原理 相机标定 相机内参标定 逆透视标定 单目测距标定

<网络安全>《26 工控漏洞挖掘平台》

1 概念 工控漏洞挖掘平台综合应用各种技术和工具发现工业控制系统潜在的漏洞&#xff0c;对安全性和健壮性进行测试&#xff0c;深度挖掘工控设备或系统的各类已知和未知漏洞&#xff0c;清晰定位问题&#xff0c;明确漏洞形成的机理和相应的攻击方法&#xff0c;为漏洞的弥补…

新版MQL语言程序设计:状态模式的原理、应用及代码实现

文章目录 一、什么是状态模式二、状态模式的实现原理三、状态模式的应用场景四、状态模式的代码实现 一、什么是状态模式 状态模式是一种行为设计模式&#xff0c;它允许对象在内部状态改变时改变其行为。在状态模式中&#xff0c;对象的行为取决于其内部状态&#xff0c;并且可…

【大厂AI课学习笔记】【1.6 人工智能基础知识】(3)神经网络

深度学习是机器学习中一种基于对数据进行表征学习的算法。观测值(例如一幅草莓照片)可以使用 多种方式来表示&#xff0c;如每个像素强度值的向量&#xff0c;或者更抽象地表示成一系列边、特定形状的区域等。 深度学习的最主要特征是使用神经网络作为计算模型。神经网络模型 …

跨站请求伪造 CSRF 漏洞原理以及修复方法

漏洞名称&#xff1a;跨站请求伪造&#xff08;CSRF&#xff09; 漏洞描述&#xff1a; 跨站请求伪造攻击&#xff0c;Cross-Site Request Forgery&#xff08;CSRF&#xff09;&#xff0c;攻击者在用户浏览网页时&#xff0c;利用页面元素&#xff08;例如img的src&#xf…

【echarts】入门示例

1、引入echarts.js文件 2、准备一个呈现图表的盒子 3、初始化echarts实例对象 4、准备配置项 5、将配置项设置给echarts实例对象 <!DOCTYPE html> <html><head><meta charset"utf-8" /><title>ECharts</title><!-- 引入刚刚…

seatunnel数据集成(二)数据同步

seatunnel数据集成&#xff08;一&#xff09;简介与安装seatunnel数据集成&#xff08;二&#xff09;数据同步seatunnel数据集成&#xff08;三&#xff09;多表同步seatunnel数据集成&#xff08;四&#xff09;连接器使用 1、Connector类型 seatunnel连接器类型丰富&#…

【Java】乐观锁、悲观锁、可重入锁、不可重入锁的关系是什么?

乐观锁、悲观锁、可重入锁和不可重入锁是Java中不同的锁策略和实现方式&#xff0c;它们之间的关系可以从以下几个方面来理解&#xff1a; 乐观锁与悲观锁&#xff1a;这两种锁代表的是不同的加锁策略&#xff0c;而不是具体的锁实现。乐观锁假设冲突不会频繁发生&#xff0c;因…