第三方C代码移植过程中的typedef重复定义问题

【CPP知识】typedef数据类型重定义 3.1 、简化类型申明,比如原来的数据类型long double,可以更见简化成my_float;int x;int y;int z;} sample;// 使用typedef简化了类型 sample s1 = {// 以下是不使用typedef则显得复杂。int y;int z;} s2 = {3.2、简化函数申明,time_t time(time_t *); 阅读详情
AI摘要

本文探讨了在移植第三方代码到特定平台时遇到的类型定义冲突问题,特别是针对typedef INT32类型的重复定义,并提出了三种解决方案:extern声明法、统一typedef法及类型适配法。

楔子:

本文主要描述了把第三方代码移植到某一目标平台过程中所发生的typedef重复定义的问题。之所以要写这个问题,原因有三:1>这个问题是一个移植代码过程中经常遇到的老大难问题2>我还没有完全(或者说完美的)解决这个问题3>想得到诸位高手的点拨。

首先要看看下面的原始代码(为了突出重点,我简化了代码结构。实际代码要复杂的多):

a.c和a.h代表主开发平台的代码,下面简称为A平台代码;b.c和b.h代表要移植到A平台的第三方的代码,下面简称为B代码。

<代码片断I>
//filename: b.h
#ifndef B_H
#define B_H

typedef long INT32;

void b_bar(INT32 num);

#endif //B_H
//filename: b.c

#include <stdio.h>
#include "b.h"

void b_bar(INT32 num)
{
 printf("b_bar trace: %d\n", num);
}


//filename: a.h
#ifndef A_H
#define A_H

typedef short INT32;

void a_foo(INT32 num);

#endif //A_H
//filename: a.c
#include <stdio.h>
#include "a.h"

void a_foo(INT32 num)
{
 printf("a_foo trace: %d\n", num);
}

int main()
{
 INT32 abc=100;
 a_foo(abc);
}

源代码中A代码和B代码中并无任何瓜葛。A代码和B代码中都定义了一个叫做INT32的类型,但是在A代码中INT32是以short为原型的,就是说A代码中所有使用INT32的类型都是期望使用short的。同理,B代码中的所有使用INT32类型的地方都是期望使用long的。因此,我们只要在移植过程中保证A代码和B代码中的类型定义都满足自己原始的期望,那么这个移植过程中类型定义就是成功的,代码运行起来也就会很稳定;反之,移植的代码就存在着极大的风险。

现在进入正题。我们想在a.c中使用B代码中的b_bar()这个函数,常规的方法是这样的:

<代码片断II>
//filename: a.c
#include <stdio.h>
#include "a.h"

//////// Add this include sentence,We want use B 's declare
#include "b.h" 

void a_foo(INT32 num)
{
 printf("a_foo trace: %d\n", num);
}

void a_xxx(INT32 num)  ///////// Add this function
{
 printf("a_xxx trace: %d\n", num);
 b_bar(num);   ///////// Call b_bar() function
}

int main()
{
 INT32 abc=100;
 a_foo(abc); 
 a_xxx(abc);  ///////// Use a_xxx() function
}
但是,我们代码如果这么使用的话,就会出错。错误的原因大概是:redefinition; different basic types。重复定义,不一致的基本类型。因为A代码和B代码中都定义了INT32这个类型。

那么我们应该如何搞定?有大概三种方法来解决这个问题,我们一一来看。


一、extern声明法

这种方法的基本思想是讲问题由编译阶段推迟到链接阶段。我一般会优先使用这种方法,代码如下:

<代码片断III>
//filename: a.c
#include <stdio.h>
#include "a.h"

///Use extern declare instead of include sentence, and use long instead of INT32
extern void b_bar(long num);

void a_foo(INT32 num)
{
 printf("a_foo trace: %d\n", num);
}

void a_xxx(INT32 num)  ///////// Add this function
{
 printf("a_xxx trace: %d\n", num);
 b_bar(num);   ///////// Call b_bar() function
}

int main()
{
 INT32 abc=100;
 a_foo(abc); 
 a_xxx(abc);  ///////// Use a_xxx() function
}
如上面代码所示,我不再在A代码里面include B代码的.h文件,这样就避免了typedef的重复定义。同时,我修改了extern的b_bar()的声明,使其使用C语言基本类型long,这样就满足了B代码的原始期望,B代码运行起来就不会有错。通过extern,将问题推迟到链接期,链接的过程中是以原始类型为基准的,所以链接起来也不会出错。基本上就解决了这个问题。


方法一的缺点:1>修改extern的B代码的声明中的类型为基本类型,看起来代码不是很优雅;2>如果A代码中多处使用B代码,或者要使用B代码中的多个函数,大量的extern将使代码看起来非常的恶心。


二、统一typedef法

我所使用的X公司的源代码实际上也是有好几个部分拼接而成的,每个部分都有自己的typedef。它的代码中通过如下方法来规避typedef重复定义的问题:

<代码片断IV>
//filename: b.h
#ifndef B_H
#define B_H


#ifndef A_H
typedef long INT32;
#endif

void b_bar(INT32 num);

#endif //B_H
修改b.h,而b.c、a.h 使用代码片断1的,a.c使用代码片断2的。


这样一来,B代码在b.h进行typedef的时候,如果检测到目前代码中已经存在了INT32这个定义,就不在进行这个定义了,就使用现存的INT32这个定义。这样一来,其实B代码在使用short来替代INT32,而不是它的原始期望中的long。我个人认为,这会导致B代码中的某些实现不稳定、出错。所以在移植第三方代码过程中,我绝对不推荐这种用法。(这是开讨论会中争议最大的地方,如果你有金砖,千万不要吝惜,拍过来吧~~让暴风雨来的更猛烈些吧)


三、类型适配法

这段文字已经不是再解决上面的问题了,纯粹是做为一种引申的思路而已。某些公司的代码会提供自己名字前缀的typedef,如ABC公司的类型定义就是ABC_INT32,而XXX公司的类型定义就是XXX_INT32。这样就能保证自己的类型定义总是在自己内部使用,而不至于引起冲突来。


<代码片断V>
//filename: b.h
#ifndef B_H
#define B_H

typedef long B_INT32;

void b_bar(B_INT32 num);

#endif //B_H
//filename: b.c

#include <stdio.h>
#include "b.h"

void b_bar(B_INT32 num)
{
 printf("b_bar trace: %d\n", num);
}


修a.h 使用代码片断1的,a.c使用代码片断2的。


这样就不会在A代码和B代码之间引起类型定义冲突了。如果类型定义复杂了,有可能在A和B之间要进行强制类型转换,这点的确不爽。不过一般B代码会引入一个类型适配层,用typedef来把A和B之间的类型建立等价关系,这样就一点问题也没有了。
//filename: b_type_adapt.h
typedef B_INT32 A_INT;
typedef B_UINT32 A_UINT;


在A代码中使用B代码的时候就include这个b_type_adapt.h,这样A就能正确识别出B的类型来。问题就完全解决了。


总结:遗憾的是,有很多公司的代码都不是按照方法3来做的,它们都认为自己比较牛,自己应该定义原始类型,%^&(×)#%¥^&…… 唉,就苦了我们porting engineer了。因为是做porting,所以我不能把B中的typedef的类型做个全文替换,这样以后升级B代码就更头疼了。唉,这年头混口饭吃不容易阿~~
Ubuntu 22.04 安装 PostgreSQL + AGE + pgvector 完全指南 本教程详细介绍了在Ubuntu 22.04服务器上安装PostgreSQL数据库,并为其添加AGE图数据库扩展和pgvector向量搜索扩展的步骤。首先,更新系统并安装PostgreSQL,然后通过源码构建并安装AGE和pgvector扩展。接着,配置PostgreSQL以使用这些扩展,并可选地允许远程连接。教程还包括创建用户、设置密码、验证安装以及安装后的优化建议。最后,提供了常见问题的解决方法。通过本教程,用户可以在同一数据库中处理关系型数据、图数据和向量数据,为现代应用程序提供强大的数据支持。 阅读详情

相关推荐

LeGO-LOAM相对LOAM的改进---地面分离的方法-算法原理+代码讲解

实际上此种地⾯分离算法有⼀些简单,我们可以结合激光雷达安装⾼度等其他先验信息进⾏优化,避免将桌子这些当作地面点。LeGO-LOAM中前端改进中很重要的⼀点就是充分利⽤了地⾯点,那⾸先⾃然是提取对地⾯点的提取。理想情况下, 应该接近0,考虑到⼀⽅⾯激光雷达安装也⽆法做到绝对⽔平,另⼀⽅⾯,地⾯也不是绝。对⽔平,因此,这个⾓度会略微⼤于0,考虑到作者实际在草坪之类的场景下运动,因此这个值被设置成。如上图,相邻的两个扫描线束的同⼀列打在地⾯上如AB点所⽰,他们的垂直⾼度差。,计算垂直⾼度差和⽔平⾼度差的⾓度。..

zysss_的博客 775

typedef重定义错误

记录一个问题。 Item.h文件: typedef int Item; Link.h文件: #include "Item.h" void LINKinit(int); Link.c文件: #include "stdio.h" #include "Link.h" #inlcude "Item.h" void LINKint(int n) {

wangst4321的专栏 8445

新能源知识库(62)组串式、集中式和高压直挂式

因需多台PCS及独立监控设备,单位功率成本比集中式高15%–20%。高压直挂式因省去变压器,大容量项目成本更低(>5MW时优势显著)。组串式储能、集中式储能和高压直挂式储能是当前主流的三类技术路线,其核心差异源于系统架构和控制逻辑的设计差异。组串式交流侧需变压器升压至10kV/35kV,高压直挂式可直接输出6kV/35kV电压,减少转换损耗。多台小功率PCS并联(每簇独立管理)单台大功率PCS(多簇直流侧并联)环流导致容量衰减(损失5%–8%)无变压器损耗(效率>99%)高压直挂电站(≥10MW)

竹君子之家 1515

typedef重复定义的一种解决方法

与#define不同,typedef没有类似#undef的方法取消定义,如果两个库中同时使用typedef定义了某个类型,便会编译失败。 一个解决方法是,在包含第二个库时使用#define将重复定义的类型名改掉。 例如,如果头文件sm_system.h和math.h中均包含"typedef xxxx float_t"语句,那么使用如下的头文件包含方法: ...

baihu9067的博客 9943

别再折腾老教程了!树莓派4B/5最新系统(Raspberry Pi OS Bookworm)红外遥控配置,用gpio-ir驱动一次成功

本文详细介绍了树莓派4B/5在最新Raspberry Pi OS Bookworm系统下配置红外遥控的完整指南,摒弃过时的lirc-rpi驱动,采用现代gpio-ir驱动方案。从硬件连接到软件配置,提供10分钟快速上手指南,涵盖驱动加载、信号测试、按键映射及高级应用场景,帮助用户高效完成红外遥控配置。

weixin_42520909的博客 442

Pixel 4/4 XL 刷机小白必看:Magisk Root 全流程详解(附电信网络适配技巧)

本文为Pixel 4/4 XL用户提供了一份详尽的Magisk Root全流程指南。从解锁Bootloader、刷入Magisk,到解决电信网络VoLTE适配问题,再到隐藏Root以通过银行App检测,手把手教你安全获取系统最高权限并优化日常使用体验。

weixin_29310605的博客 264

用typedef 将结构体重定义时遇到的问题

Linklist 定义L为二级指针,编译时遇到错误。我没有给结构体命名,所以无法进行声明其它的变量 L;改为 typedef struct list{

m0_54797575的博客 660

现控报告-- 分析倒立摆系统稳定性、能控性及能观性分析,设计PID控制方案(附matlab)

建立直线一级倒立摆系统的动力学模型,推导该系统的运动方程,求出直线一级倒立摆系统传递函数模型及空间状态方程模型。接着描述了PID控制系统设计原理及PID控制器各校正环节的作用,简要叙述了参数的整定方法。设计了直线一级倒立摆摆杆摆角及小车位置常规单回路控制器,通过Simulink仿真知道常规单回路控制器能控制摆杆摆角,不能控制小车位置。于是设计出了直线一级倒立摆双闭环控制器及基于倒立摆系统的状态空间方程控制器,利用软件进行仿真,仿真结果表明,常规双闭环控制方案和基于状态空间方程加控制方案均能对摆杆摆角及小车位

mengshenglo的博客 4万+

第三方C代码移植过程中的TYPEDEF重复定义问题

原文http://blog.vckbase.com/smileonce/archive/2005/08/06/10547.aspx 第三方C代码移植过程中的TYPEDEF重复定义问题 楔子:   本文主要描述了把第三方代码移植到某一目标平台过程中所发生的typedef重复定义的问题。之所以要写这个问题,原因有三:1>这个问题是一个移植代码过程中经常遇到的老大难问题2>我还没有完全

maoranbian的area 2479

Doorbell机制在PCI与MSI中断中的高效应用

本文深入解析了Doorbell机制在PCIe设备与CPU间通信中的核心作用。作为一种高效的硬件通知机制,它通过内存映射I/O(MMIO)实现软件对硬件的轻量级触发,常与MSI中断协同工作,构建高效的生产者-消费者模型。文章以AMD GPU的Ring Buffer命令提交为例,阐述了该机制如何显著降低CPU开销、提升系统吞吐量,并对比了其与传统中断方式的性能优势。

ee345的博客 608

配置某VLAN下ONU的二层互访(隔离)问题(解决OLT二层隔离问题)

问题:OLT的ONU节点之间在同一VLAN下的终端默认隔离,在确实需要互通的场景下如何解决。

symstandsun的博客 4564

【C/C++】typedef用法详解

typedef 声明,简称 typedef,人们常常使用 typedef 来编写更美观和可读的代码。所谓美观,意指 typedef 能隐藏笨拙的语法构造以及平台相关的数据类型,从而增强可移植性和以及未来的可维护性。本文下面将竭尽全力来揭示 typedef 强大功能以及如何避免一些常见的陷阱。 一、typedef的四个用途 1.1、用途一:定义一种类型易于记忆的别名,而不只是简单的宏替换。 a...

qq_34018840的博客 5829

硬方案——几种实用的恒流源电路设计方案,敬请收藏(运放、三极管在手,让你玩出多种花样)

0 引言 我们在信号测量、供电等应用场景时常会涉及到使用恒流源,以前觉得恒流源挺神奇的,研究了下实现方案,其实也没有多么高深(这里讨论的仅限于用在信号测量中的小电流恒流源设计),这里给出几个实用的恒流源电路设计方案。 1 恒流源电路设计 (1)使用三极管搭建的恒流源 (2)使用运放搭建的恒流源 (3)使用恒流二极管搭建的恒流源 pt100恒流源测温电路图_电子技术_电工之家 ...

数字世界 万物互联 9524

Typedef Struct 用法详解

Typedef Struct 用法详解 一、typedef的用法 在C/C++语言中,typedef常用来定义一个标识符及关键字的别名,它是语言编译过程的一部分,但它并不实际分配内存空间。 实例像: typedef int INT; typedef int ARRAY[10]; typedef (int*) pINT; typedef可以增强程序的可读性,以及标识符的灵活性...

PengCoX 9936

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

c语言typedef(c语言typedef和define)

什么是C语言 C語言是1972年左右由DennisRitchie一??人在?????室(?稱AT&T)設?開發出?淼碾?腦程式語言.他??r與KenThompson?扇斯餐??UNIX作?I系統的發展,而 UNIX作?I系統(是一??多人多工的作?I系統)與大部份的公用程式及C本身的?譯器( Compiler)...

计算机毕业论文源码,学生个人网页制作html源码。贴近用户做网络推广和互联网优化。 508

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

有关typedef定义新的类型名的作用

一般形式:typedef已有类型新类型名;一旦重命名类型,就可以以新类型名来描述数据。习惯上新类型名用大写字母表示。例如:(1)typedef int integer;/*重命名整型*/integer i,j;(2)typedef int COUNT;/*命名一计数类型COUNT*/COUNT n1,n2;(3)typedef int NUM[100];/*命名一整型数组类型NUM*/NUM n:

陶野的窝 4360

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

【总结】C语言中typedef语句用法

1Typedef声明有助于创建平台无关类型,甚至能隐藏复杂和难以理解的语法。typedef声明,简称typedef,为现有类型创建一个新的名字。比如人们常常使用 typedef 来编写更美观和可读的代码。 typedef 能隐藏笨拙的语法构造以及平台相关的数据类型,从而增强可移植性和以及未来的可维护性。  例如:typedef int size;  此声明定义了一个 int 的同义字,

qq_37660535的博客 291

C语言——C程序编译过程

C程序的编译过程 - 预处理 - 编译 - 汇编 - 链接

努力,奋斗! 3149

C语言:关于typedef的几种用途

    在C还是C++代码中,typedef都使用的很多,在C代码中尤其是多。typedef与#define有些相似,其实是不同的,特别是在一些复杂的用法上,看了网上一些C/C++的学习者的博客,其中有一篇关于typedef的总结还是很不错,由于总结的很...

weixin_44498318的博客 1589

C/C++ typedef用法

引言 typedef 声明,简称 typedef,为现有类型创建一个新的名字。比如人们常常使用 typedef 来编写更美观和可读的代码。所谓美观,意指 typedef 能隐藏笨拙的语法构造以及平台相关的数据类型,从而增强可移植性和以及未来的可维护性。 在编程中使用typedef目的一般有两个,一个是给变量一个易记且意义明确的新名字,另一个是简化一些比较复杂的类型声明。 typedef的使用方法如...

十年代码写十年 1426

C语言中的typedef

typedef声明,简称 typedef,为现有类型创建一个新的名字。比如人们常常使用 t ypedef来编写更美观和可读的代码。所谓美观,意指typedef能隐藏笨拙的语法构造以及平台相关的数据类型,从而增强可移植性和以及未来的可维护性。      typedef使用最多的地方是创建易于记忆的类型名,用它来归档程序员的意图。类型出现在所声明的变量名字中,位于 ''typedef''关键字右边

张勤一 2047

C++类型定义(typedef)

C++类型定义(typedef) 上节我们介绍了枚举类型(enum)。C/C++枚举类型 本节我们介绍类型定义。 引入: 在写代码的过程中,经常会遇到使用重复的类型,这些类型名可能会很长,比如自己定义的结构体类型名,枚举类型名等等 这个时候对于这种使用频率较高,长度过长就可以使用类型定义(typedef)。相当于给类型一个别名。 例如上节中介绍的枚举类型: #include <iostream> using namespace std; //定义一个枚举类型 enum Season

qq_44989173的博客 752

C/C++——typedef用法小结

<br /><br />来源一:Using typedef to Curb Miscreant Code<br />      Typedef 声明有助于创建平台无关类型,甚至能隐藏复杂和难以理解的语法。不管怎样,使用 typedef 能为代码带来意想不到的好处,通过本文你可以学习用 typedef 避免缺欠,从而使代码更健壮。<br />      typedef 声明,简称 typedef,为现有类型创建一个新的名字。比如人们常常使用 typedef 来编写更美观和可读的代码。所谓美观,意指 typed

shineHoo的专栏 1010

C/C++ typedef用法!

引言 typedef 声明,简称 typedef,为现有类型创建一个新的名字。比如人们常常使用 typedef 来编写更美观和可读的代码。所谓美观,意指 typedef 能隐藏笨拙的语法构造以及平台相关的数据类型,从而增强可移植性和以及未来的可维护性。 在编程中使用typedef目的一般有两个,一个是给变量一个易记且意义明确的新名字,另一个是简化一些比较复杂的类型声明。 typedef的...

HUYA69的博客 755
上一篇: 一个很好的makefile教程2(转载)
下一篇: NSIS制作安装文件攻略
beyondchx
博客等级 码龄19年 238粉丝 6原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值