关于typedef的用法总结

2023-11-04

typedef的应用

typedef是C 语言中用于为现有数据类型指定替代名称的关键字。它主要用于用户定义的数据类型,当数据类型的名称在程序中使用变得稍微复杂时。以下是使用的一般语法

typedef <existing_name> <alias_name>

应用一:结构体别名

typedef也可用于为用户定义的数据类型命名。让我们看看它对结构体的使用。

// ======== old
struct type_name
{
    type member1;
    type member2;
    type member3;
};
struct type_name name;

// ========== 分割线
typedef struct
{
    type member1;
    type member2;
    type member3;
} type_name;
type_name name; // 这样就比原来的方式少写了一个struct,比较省事,尤其在大量使用的时候

应用二:类型别名

定义一种类型的别名,而不只是简单的宏替换。可以用作同时声明指针型的多个对象。例如:

int* x, y;

通过这个声明语句,我们实际上声明一个类型为int的指针x,而y则任然声明为一个普通int变量。但是如果我们typedef像在上面的例子中使用的那样使用,我们可以在单个语句中声明任意数量的指针。

typedef int* IntPtr;
IntPtr x, y, z;

但是,有一点需要注意的是,类型别名是别名,但不是全等。例如

typedef int* intptr;
const intptr x; // x是一个const pointer,指向int

不等同于:

const int *x; // x是一个指针,指向const int

intptr是指向 int 的指针。const intptr 是一个const pointer 指向 int, 而不是指向 const int。所以,在 typedef pointer 之后,不能再让它成为content的常量了?即x++将报错。

其相当于:

int * const x;

在标准库中也有些丑陋的实现,比如 gcc 的typeof 宏:

typedef int* intptr;
intptr dummy;
const typeof(*dummy) *x;

应用三:适配解耦

比如定义一个叫 REAL 的浮点类型,在系统Platform A上,让它表示最高精度的类型为:

typedef long double REAL;

在不支持 long double 的系统Platform B上,改为:

typedef double REAL;

在连 double 都不支持的系统Platform C上,改为:

typedef float REAL;

也就是说,当跨平台时,只要改下 typedef 本身就行,或者使用宏开关控制即可,将对应类型与平台解耦。

#ifdef PlatformA
	typedef long double REAL;
#elseif Platform B
	typedef double REAL;
#elseif Platform C
	typedef float REAL;
#else
	typedef void REAL;
#endif

标准库就广泛使用了这个技巧,比如size_t。

应用四:代码灵活性

为复杂的声明定义一个新的简单的别名。方法是:在原来的声明里逐步用别名替换一部分复杂声明,如此循环,把带变量名的部分留到最后替换,得到的就是原声明的最简化版。举两个例子:

  • 原声明一:
void (*b[10]) (void (*)());

变量名为b,先替换右边部分括号里的,pFunParam为别名一:

typedef void (*pFunParam)();

再替换左边的变量b,pFunx为别名二:

typedef void (*pFunx)(pFunParam);

原声明的最简化版:

pFunx b[10];
  • 原声明二:
doube(*)() (*e)[9];

变量名为e,先替换左边部分,pFuny为别名一:

typedef double(*pFuny)();

再替换右边的变量e,pFunParamy为别名二

typedef pFuny (*pFunParamy)[9];

原声明的最简化版:

pFunParamy e;

理解复杂声明可用的“右左法则”:从变量名看起,先往右,再往左,碰到一个圆括号就调转阅读的方向;括号内分析完就跳出括号,还是按先右后左的顺序,如此循环,直到整个声明分析完。

另外,void*在C语言作为万能指针,因为C中的非强耦合,很多时候利用其强转保持代码的复用性、灵活性, 声明为用户类型和用户指针类型也稍许不同,但本质都计算地址偏移。

#ifdef __cplusplus

extern "C" {
    #include <stdio.h>

    typedef void (CbkFuncPoint)(int i, int j); // void

    void (*CbkFunc)(int i, int j); // void *
    typedef void (*CbkFuncVar)(int i, int j); // void *


    struct TestStru {
        int id;
        void *func;
    };

    void testCbk(int i, int j)
    {
        printf("TestCbk %d\n", i+j);
    }

    void testCbk2(int i, int j, int k)
    {
        printf("TestCbk2 %d\n", i+j);
        (void)k;
    }

    int main()
    {
    #if 1
        CbkFunc = &testCbk;
        testCbk(0, 10);
        ((CbkFuncPoint*)testCbk)(0, 10);

        CbkFuncPoint *FuncPoint;
        FuncPoint = testCbk;
        FuncPoint(0, 10);

        CbkFuncVar FuncVar;
        FuncVar = &testCbk;
        FuncVar(0, 10);
    #endif

        struct TestStru struvar = {
            10, (void *)testCbk
        };

        (*((CbkFuncPoint*)struvar.func))(10, 20);
        ((CbkFuncPoint*)struvar.func)(10, 20);
        (*((CbkFuncPoint*)testCbk))(30, 40); // (void(*)(int, int))&testCbk
        (*((CbkFuncPoint*)testCbk2))(30, 40); // 参数不一致的特殊情况也能强转匹配

        void *tt = (void *)testCbk;
        ((CbkFuncPoint*)tt)(40, 50);

        return 0;
    }
}

#endif

参考资料

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关于typedef的用法总结 的相关文章

  • [原]Pro*C介绍-内嵌SQL

    Translate by Z Jingwei Document address http www db stanford edu ullman fcdb oracle or proc html Pro C介绍内嵌SQL 概要 Pro C语法
  • 范围for语句

    C 新标准提供的范围for语句 这种语句遍历给定序列中个元素并对序列中每一个值执行某种操作 其语法形式是 for declaration expression statement 其中 expression 部分是一个对象 用于表示一个序列
  • C++ 中的虚函数及虚函数表

    C 中的虚函数及虚函数表 一 虚函数及虚函数表的定义 二 虚函数表指针和虚函数表的创建时机 三 虚函数实现多态的原理 一 虚函数及虚函数表的定义 虚函数 虚函数就是在基类中定义一个未实现的函数名 使用虚函数的核心目的就是通过基类访问派生类定
  • 五. python面向对象(多态 和metaclass=abc.ABCMeta)

    一 多态 多肽 一种事物的多种形态 叫多肽 例如 动物 animal 猫 狗 animal py 文件 动物类 都有名字这个属性 和吃这个方法 class Animal object def init self name self name
  • 编写递归算法,计算二叉树叶子结点的数目。

    编写递归算法 计算二叉树叶子结点的数目 编写递归算法 计算二叉树叶子结点的数目 include stdio h 包含 getchar scanf printf include malloc h malloc 动态申请空间 函数 二叉树 结点
  • C语言pcre库的使用及验证IP地址的合法性

    PCRE是一个用C语言编写的正则表达式函数库 它十分易用 同时功能也很强大 性能超过了POSIX正则表达式库和一些经典的正则表达式库 在使用PCRE库时 首先肯定是需要安装pcre的 不过一般的系统都会有自带的PCRE库 不过如果想使用最新
  • FLOPS、TOPS和FLOPs的区别

    FLOPS 即每秒浮点运算次数 是每秒所执行的浮点运算次数 Floating point operations per second 缩写 FLOPS 的简称 被用来评估电脑效能 FLOPs 注意s小写 是floating point op
  • C/C++中浮点数格式学习——以IEEE75432位单精度为例

    这是浮点数的通常表示形式 在IEEE754中 单精度浮点数有如下形式 32位单精度 单精度二进制小数 使用32个比特存储 1 8 23位长 S Exp Fraction 31 30至23偏正值 实际的指数大小 127 22至0位编号 从右边
  • 互联网创业盈利模式指南

    看了很多创业的case 都有点下笔千言 离题万里的 情况 就是很多case都很精彩 但是公司 的价值最终是落实到 给创业者和投资人的回报的 因此 所有的case 最终都是 落实到盈利 模式上 一位投资人士说的很明确 中国的盈利模式很简单 就
  • Lua和C++交互总结(很详细)

    出处 http blog csdn net shun fzll article details 39120965 一 lua堆栈 要理解lua和c 交互 首先要理解lua堆栈 简单来说 Lua和C c 语言通信的主要方法是一个无处不在的虚拟
  • LeetCode题目笔记——17.19消失的两个数字

    文章目录 题目描述 题目难度 困难 方法一 暴力 代码 代码优化 方法二 数学方法 代码 总结 题目描述 题目直达 题目难度 困难 方法一 暴力 虽然题目说你能在 O N 时间内只用 O 1 的空间找到它们吗 但是也没有限制我们不能用暴力
  • c语言判断一个数是否为偶数

    include
  • Dev-C++之开启装逼效果

    Dev C 是个不错的C IDE 在10年前 它是很不错 在现在 它是个以界面丑陋和调试像吃粑粑这两点著称 如下图 实在是丑到离谱 丑到无法忍受 可是没办法呀 人家CCF规定比赛用这个 你个小蒟蒻吵什么 我现在就来讲讲怎么把你的Dev C
  • 手把手教你如何写一个三子棋/N子棋的小游戏

    这里写目录标题 第一步 游戏进入界面 第二步 初始化棋盘 第三步 打印棋盘 第四步 玩家和电脑下棋 第五步 判断输赢 三子棋或者N子棋怎么写 让我们先来玩一把 再来看看怎么写 程序运行界面 1为玩游戏 2为清屏 0为退出游戏 我们选1 然后
  • stat 函数解析

    stat 函数的简单使用 stat 函数是用来获取文件的各种属性的一个linux下的常用API函数 函数原型为int stat const char path struct stat buf stat定义如下 struct stat dev
  • C 语言教程:数据类型和格式说明符

    C 语言中的数据类型 C 中的变量必须是指定的 数据类型 并且您必须在 printf 函数中使用 格式说明符 来显示它 创建变量 int myNum 5 整数 没有小数点 float myFloatNum 5 99 浮点数 char myL
  • C++中的并发多线程网络通讯

    C 中的并发多线程网络通讯 一 引言 C 作为一种高效且功能强大的编程语言 为开发者提供了多种工具来处理多线程和网络通信 多线程编程允许多个任务同时执行 而网络通信则是现代应用程序的基石 本文将深入探讨如何使用C 实现并发多线程网络通信 并
  • C 语言运算符详解

    C 语言中的运算符 运算符用于对变量和值进行操作 在下面的示例中 我们使用 运算符将两个值相加 int myNum 100 50 虽然 运算符通常用于将两个值相加 就像上面的示例一样 它还可以用于将变量和值相加 或者将变量和另一个变量相加
  • 在 OS X 上的 virtualenv 中安装 scrapy 加密时发生错误 [关闭]

    Closed 这个问题需要调试细节 help minimal reproducible example 目前不接受答案 我正在安装 scrapypip in virtualenv on OS X 10 11 当它安装密码学时 它说 buil
  • 在 Solaris 上,使用 gcc 编译的库与使用 cc 生成的库的使用方式是否相同?

    我目前正在尝试编译 libxml2在 Solaris 上 当我运行源代码提供的 configure 脚本时 会自动使用 gcc 和 g 编译器 但是 我想使用 cc 和 CC 编译器 所以我跑 configure CC cc CXX CC

随机推荐

  • Proteus实现555计时器模拟简易电子琴

    555计时器模拟简易电子琴 一 元器件介绍 二 原理分析 三 仿真实验 实现弹奏过程 一 元器件介绍 这里用到的元器件有 RESISTOR 电阻器 CAP 电容器 BUTTON 按钮 555 555计时器 BUZZER ACTIVE 有源蜂
  • Nacos 搭建和使用

    说明 官方文档 https nacos io zh cn docs what is nacos html 粘贴一下Nacos地图 逻辑架构及其组件介绍 服务管理 实现服务CRUD 域名CRUD 服务健康状态检查 服务权重管理等功能 配置管理
  • 4G网关8305LN远程监控西门子触摸屏SMART 700IE ZLAN8305LN应用

    1 概述 ZLAN8305LN是一款专门为工业环境设计的RS485设备数据采集器 物联网网关 他通过4G的方式传输 结合卓岚特有的P2P技术 无需构建公网服务器也可以同样随时随地采集设备的数据 本次案例主要是实现目的 对SMART700IE
  • 涉及Radio传值的写法

    博主最近在帮朋友做毕设 需要新增一个功能 功能里面有个radio列表 需要传radio元素的id值到后台 尝试了好多种写法都不行 最后用了下面的写法就好 后台顺利接收到参数 话不多说 直接上图 要如图红框里面的写法才能取到被选中的选项ID的
  • Mysql8.0的安装与配置(图文超详细)

    MySQL8 0安装配置 1 软件下载 2 软件安装 3 软件配置 4 环境变量配置 1 软件下载 链接 https pan baidu com s 1gyNz1o7SCyLIfoNcBUKRIQ 提取码 ajpl 2 软件安装 1 下载好
  • vue 收藏和取消收藏的点击事件

    描述 点击 取消收藏 图标切换 文字变为 收藏 收藏状态变为 未收藏 刷新页面 未收藏 数据不再显示 思路 通过if判断 给定这条数据一个状态 点击改变状态值 状态需要后端在接口里返回 未点击时 图标亮 状态为true 点击时 图标灰 数据
  • Qt 自定义数据类型在信号和槽中的传递

    Qt 信号和槽函数参数只能是基于 Qt 的基础类型的 比如 QString int bool 等 如果想传递自定义类型默认情况下是行不通的 下面以结构体为例 实现结构体类型数据的传递 头文件 ifndef MAINWINDOW H defi
  • 可视化分组散点图并添加分层线性回归模型的拟合曲线(使用R语言)

    可视化分组散点图并添加分层线性回归模型的拟合曲线 使用R语言 在数据分析和可视化中 经常需要绘制散点图以观察两个变量之间的关系 并使用回归模型来拟合数据 本文将介绍如何使用R语言创建分组散点图 并添加分层线性回归模型的拟合曲线 首先 我们需
  • 【操作系统】王道考研 p50-51 文件的物理结构(文件分配方式)

    文件的物理结构 上 文件的物理结构 下 知识总览 文件块 磁盘块 磁盘块的大小与内存块 页面的大小相同 内存与磁盘之间的数据交换以 块 为单位 在外存管理中 文件的逻辑地址空间被分为一个个文件块 连续分配 连续分配要求每个文件在磁盘上占有一
  • Integer的缓存机制、自动装箱拆箱

    一 什么是自动装箱拆箱 很简单 下面两句代码就可以看到装箱和拆箱过程 自动装箱 Integer total 99 自动拆箱 int totalprim total 简单一点说 装箱就是自动将基本数据类型转换为包装器类型 拆箱就是自动将包装器
  • 五行中的土在哪个方位_五行代表的方位

    五行方位 东 南 中 西 北 论 五 行 生 成 五行是构成宇宙万物的五种元素 它们是变化无穷 高深莫测的 五行的创立 準确地模拟了自然界的状态 宇宙万物的生息变化都不能离开五行 五行的顺序 一水 二火 叁木 四金 五土 这个顺序列取决于地
  • go性能优化

    常规手段 1 sync Pool 临时对象池应该是对可读性影响最小且优化效果显著的手段 最典型的就是fasthttp了 它几乎把所有的对象都用sync Pool维护 但这样的复用不一定全是合理的 比如在fasthttp中 传递上下文相关信息
  • 【故障诊断】基于最小熵反卷积、最大相关峰度反卷积和最大二阶环平稳盲反卷积等盲反卷积方法在机械故障诊断中的应用研究(Matlab代码实现)

    个人主页 研学社的博客 欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 2 1 稀疏最大谐波噪声比反卷积 2 2 最大相关峰度反卷积 2 3
  • 认知计算导论自救版笔记

    认知计算导论 认知数据收集 认知cognitive数据 1 定义 认知物联网IoT 认知系统和互联网组合 认知数据来源 物理世界 互联网提供大量数据 虚拟世界 社交网络和移动计算 人群感知Crowd Sensing 大量人群通过移动设备无意
  • vst开启语音服务器,VST语音遥控器体验记

    体验信息 101245hu4k1a42krae4l4s jpg 10 39 KB 下载次数 5 2015 5 30 16 34 上传物品名称 VST智能语音遥控器适配物品 101502huualwallumcbaaa jpg 3 35 KB
  • 基于数组的链表AList

    快考试了 作为数据结构的复习 那么就把代码背打一遍好了 虽然代码很简单 但是把基础打牢固对以后的学习肯定是百益而无一害 正好也练练C 模板和指针以及代码书写的模块化 否则天天写些算法程序 一写就一大坨 乱乱的 养成习惯就悲剧了 看一点写一点
  • 梅尔频率倒谱系数(MFCC)

    https blog csdn net zkl99999 article details 80723755
  • winform中如何设置splitContainer中panel的宽度,并在以后的拖动中保持不变

    搜先随便选着一个penel 按Esc键这时你会选择这个splitContainer控件 假如 你要固定penel1 这时你需要先拖动splitContainer控件 让penel1全部显示出来 然后在splitContainer控件的属性中
  • 一、Gradle入门

    文章目录 一 Gradle入门 1 1 Gradle 简介 1 2 常见的项目构建工具 1 3 Gradle 安装 1 3 1 Gradle 安装说明 1 3 2 安装 JDK 1 3 3 下载并解压到指定目录 1 3 4 配置环境变量 1
  • 关于typedef的用法总结

    typedef的应用 typedef是C 语言中用于为现有数据类型指定替代名称的关键字 它主要用于用户定义的数据类型 当数据类型的名称在程序中使用变得稍微复杂时 以下是使用的一般语法 typedef