C/C++联合union用作函数参数实例(tcy)

2024-03-20 08:48

本文主要是介绍C/C++联合union用作函数参数实例(tcy),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

说明:在此重点介绍C union的具体用法,包括函数参数,指针参数,原理不做说明。
用途:主要用在C语言或和C沟通中;在C++被std::variable替代
区别:union和std::variant
1)共同点:都应用于多个变量类型的自由选择能够保存多个类型列表中任意一个对象
2)不同点:a) 不能从union中派生类;不知当前持有值类型,因此不能有non-trivial成员如std::string(从C++11起可有non-trivial成员,必须有特殊成员函数(复制构造和析构))b) variable当前值类型已知;可有任何指定类型成员;可以派生类c) std::variant用途:用于存储和操作不同类型对象,是一个类型安全的联合体(union).variant实例存储某一类型数据,可指定重复数据类型.  注意:联合只能初始化一个参数;若联合中有字符串时当目前选项是非str按str输出用std::cout报错;非str输出不报错(不是当前类型输出无意义的值)直接使用union存在不知类型,不知是否有值的风险,正确用法是加一个type标志(参考第二部分)

 std::variant实例可参考 :  C++实现python中的列表list,dict (tcy)

第一部分:直接使用联合作为参数:存在不知类型,不知是否有值的风险

Tpar bar(const Tpar& a, int x) {Tpar b;b.l = a.l + x;return b;
}void bar(const Tpar& a, int x, Tpar* dst) {if (dst)dst->l = a.l + x;
}
Tpar bar(const Tpar* src, int x) {Tpar b;if(src) b.l = src->l + x;return b;
}void bar(const Tpar* src, int x, Tpar* dst) {Tpar b;if (dst) {if (src) dst->l = src->l + x;}
}
void print(Tpar a, const char* mode = "int",const char* no="") {if (mode = "int")std::cout << no << a.l << std::endl;else if (mode = "double")std::cout << no << a.d << std::endl;else if (mode = "str")std::cout << no << a.s << std::endl;else std::cout << "err" << std::endl;
}

 测试:

void test_bar() {Tpar a, b; Tpar *pa = &a;Tpar *pb = &b;a.l = 10;b = bar(a, 100);print(b, "int", "b1=");print(*pb, "int", "b1=");a.l = 20;bar(a, 100,pb);print(b, "int", "b2=");print(*pb, "int", "b2=");pa->l = 30;b = bar(pa, 100);print(b, "int", "b3=");print(*pb, "int", "b3=");pa->l = 40;bar(pa, 100, pb);print(b, "int", "b4=");print(*pb, "int", "b4=");
}
/*
b1=110
b1=110
b2=120
b2=120
b3=130
b3=130
b4=140
b4=140
*/

第二部分:正确用法union+1个type指示:

实例: 

void print(Tcpar a, const char* no = "") {if (a.type == 0) std::cout << no << a.par.l << std::endl;else if (a.type == 0) std::cout << no << a.par.l << std::endl;else if (a.type == 1) std::cout << no << a.par.d << std::endl;else if (a.type == 2) std::cout << no << a.par.s << std::endl;else std::cout << "err" << std::endl;
};void set_data(Tcpar& a, int v) {a.par.l = v; a.type = 0; }
void set_data(Tcpar& a, double v) {a.par.d = v; a.type = 1; }
void set_data(Tcpar& a, char* v) { a.par.s = v;a.type = 2; }
实例1:基本测试
int get_int(const Tcpar& a) {if (a.type != 0)throw std::exception("not int");return a.par.l;
};
double get_double(const Tcpar& a) {if (a.type != 1)throw std::exception("not double");return a.par.d;
};
char* get_str(const Tcpar& a) {if (a.type != 2)throw std::exception("not str");char* p = new char[255];strncpy_s(p, 255, a.par.s, 255-1);return p;
};
void get_str(const Tcpar& a,char* rst,size_t n) {if (a.type != 2)throw std::exception("not str");strncpy_s(rst, n, a.par.s, n-1 - 1);
};
实例2:函数参数
Tcpar foo(const Tcpar& a, int x) {Tcpar b;if (a.type == 0) set_data(b, a.par.l+x); else if (a.type == 1) set_data(b, a.par.d+x); else throw std::exception("param err");return b;
};Tcpar foo(const Tcpar& a, const char* x,size_t total) {Tcpar b;if (a.type == 2) {char* p = new char[total];std::string s = std::string(a.par.s) + x;strncpy_s(p, total, s.c_str(), total -1);b.par.s = p; b.type = 2;}else {throw std::exception("param err");}return b;
};void foo(const Tcpar& a, const char* x,Tcpar* out,size_t total) {if (a.type == 2) {std::string s = a.par.s + std::string(x);strncpy_s(out->par.s, total, s.c_str(), total-1);}else {throw std::exception("param err");}
};
实例3:指针参数
Tcpar foo(const Tcpar* src, int x) {Tcpar b;if (src->type == 0) set_data(b, src->par.l + x);else if (src->type == 1) set_data(b, src->par.d + x);else throw std::exception("param err");return b;
};Tcpar foo(const Tcpar* src, const char* x, size_t total) {Tcpar b;if (src->type == 2) {char* p = new char[total];std::string s = src->par.s + std::string(x);strncpy_s(p, total, s.c_str(), total - 1);b.par.s = p; b.type = 2;}else {throw std::exception("param err");}return b;
};void foo(const Tcpar* src, const char* x, Tcpar* dst, size_t total) {if (src->type == 2) {std::string s = src->par.s + std::string(x);strncpy_s(dst->par.s, total, s.c_str(), total - 1);dst->type = 2;}else {throw std::exception("param err");}
};
测试程序:
void test_union_base() {Tcpar a;a.par.l = 100; a.type = 0;print(a, "int is ");a.par.d = 3.14; a.type = 1;print(a, "double is ");char*p = const_cast<char*>("Tom");a.par.s = p; a.type = 2;print(a, "str is ");std::cout << std::endl;
}void test_set_data() {Tcpar a;char*p = const_cast<char*>("Jim");set_data(a, 200);print(a, "int is ");set_data(a, 6.28);print(a, "double is ");set_data(a, p);print(a, "str is ");std::cout << std::endl;
}
void test_get_data() {Tcpar a;set_data(a, 111);std::cout << get_int(a) << std::endl;set_data(a, 33.3);std::cout << get_double(a) << std::endl;char* p = const_cast<char*> ("China");set_data(a, p);std::cout << get_str(a) << std::endl;char arr[255];get_str(a, arr,255);std::cout << arr << std::endl << std::endl;
}
void test_foo() {Tcpar a;a.par.l = -10; a.type = 0;Tcpar b = foo(a, -100);print(b, "foo(Tcpar a,int x)=");const char* str = "Chongming"; char* p = const_cast<char*>("Shanghai-");a.par.s = p; a.type = 2;b = foo(a, str, 255);print(b, "foo(Tcpar a,const char* x,size_t total)=");p = const_cast<char*>("Nanjing-");a.par.s = p; a.type = 2;Tcpar *pb = &b;foo(a, "Gulou", pb, 255);print(b, "foo(Tcpar a,const char* x,Tcpar* out,size_t total)=");
}void test_foo_ptr() {Tcpar a, b;Tcpar *pa = &a;Tcpar *pb = &b;set_data(a, -99);b = foo(pa, -100);print(b, "b1=");char* p = const_cast<char*> ("Henan-");set_data(a, p);b = foo(pa, "Nanyang", 255);print(b, "b2=");p = const_cast<char*> ("Tianjin-");set_data(a, p);foo(pa, "Tanggu", pb, 255);print(b, "b3=");
} 
void test_union() {std::cout << "start test union base..." << std::endl;test_union_base();std::cout << "start test set union data..." << std::endl;test_set_data();std::cout << "start test get union data..." << std::endl;test_get_data();std::cout << "start test foo..." << std::endl;test_foo();std::cout << "start test foo ptr ..." << std::endl;test_foo_ptr();
}
结果:
/*
start test union base...
int is 100
double is 3.14
str is Tomstart test set union data...
int is 200
double is 6.28
str is Jimstart test get union data...
111
33.3
China
Chinastart test foo...
foo(Tcpar a,int x)=-110
foo(Tcpar a,const char* x,size_t total)=Shanghai-Chongming
foo(Tcpar a,const char* x,Tcpar* out,size_t total)=Nanjing-Gulou
start test foo ptr ...
b1=-199
b2=Henan-Nanyang
b3=Tianjin-Tanggu
*/

这篇关于C/C++联合union用作函数参数实例(tcy)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


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

相关文章

Java List排序实例代码详解

《JavaList排序实例代码详解》:本文主要介绍JavaList排序的相关资料,Java排序方法包括自然排序、自定义排序、Lambda简化及多条件排序,实现灵活且代码简洁,文中通过代码介绍的... 目录一、自然排序二、自定义排序规则三、使用 Lambda 表达式简化 Comparator四、多条件排序五、

Java实例化对象的​7种方式详解

《Java实例化对象的​7种方式详解》在Java中,实例化对象的方式有多种,具体取决于场景需求和设计模式,本文整理了7种常用的方法,文中的示例代码讲解详细,有需要的可以了解下... 目录1. ​new 关键字(直接构造)​2. ​反射(Reflection)​​3. ​克隆(Clone)​​4. ​反序列化

C++类和对象之初始化列表的使用方式

《C++类和对象之初始化列表的使用方式》:本文主要介绍C++类和对象之初始化列表的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C++初始化列表详解:性能优化与正确实践什么是初始化列表?初始化列表的三大核心作用1. 性能优化:避免不必要的赋值操作2. 强

C++迭代器失效的避坑指南

《C++迭代器失效的避坑指南》在C++中,迭代器(iterator)是一种类似指针的对象,用于遍历STL容器(如vector、list、map等),迭代器失效是指在对容器进行某些操作后... 目录1. 什么是迭代器失效?2. 哪些操作会导致迭代器失效?2.1 vector 的插入操作(push_back,

Python解决雅努斯问题实例方案详解

《Python解决雅努斯问题实例方案详解》:本文主要介绍Python解决雅努斯问题实例方案,雅努斯问题是指AI生成的3D对象在不同视角下出现不一致性的问题,即从不同角度看物体时,物体的形状会出现不... 目录一、雅努斯简介二、雅努斯问题三、示例代码四、解决方案五、完整解决方案一、雅努斯简介雅努斯(Janu

Python开发文字版随机事件游戏的项目实例

《Python开发文字版随机事件游戏的项目实例》随机事件游戏是一种通过生成不可预测的事件来增强游戏体验的类型,在这篇博文中,我们将使用Python开发一款文字版随机事件游戏,通过这个项目,读者不仅能够... 目录项目概述2.1 游戏概念2.2 游戏特色2.3 目标玩家群体技术选择与环境准备3.1 开发环境3

C#如何调用C++库

《C#如何调用C++库》:本文主要介绍C#如何调用C++库方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录方法一:使用P/Invoke1. 导出C++函数2. 定义P/Invoke签名3. 调用C++函数方法二:使用C++/CLI作为桥接1. 创建C++/CL

C++如何通过Qt反射机制实现数据类序列化

《C++如何通过Qt反射机制实现数据类序列化》在C++工程中经常需要使用数据类,并对数据类进行存储、打印、调试等操作,所以本文就来聊聊C++如何通过Qt反射机制实现数据类序列化吧... 目录设计预期设计思路代码实现使用方法在 C++ 工程中经常需要使用数据类,并对数据类进行存储、打印、调试等操作。由于数据类

Linux下如何使用C++获取硬件信息

《Linux下如何使用C++获取硬件信息》这篇文章主要为大家详细介绍了如何使用C++实现获取CPU,主板,磁盘,BIOS信息等硬件信息,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录方法获取CPU信息:读取"/proc/cpuinfo"文件获取磁盘信息:读取"/proc/diskstats"文

Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案

《Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案》:本文主要介绍Vue3组件中getCurrentInstance()获取App实例,但是返回nu... 目录vue3组件中getCurrentInstajavascriptnce()获取App实例,但是返回n