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

相关文章

C++中unordered_set哈希集合的实现

《C++中unordered_set哈希集合的实现》std::unordered_set是C++标准库中的无序关联容器,基于哈希表实现,具有元素唯一性和无序性特点,本文就来详细的介绍一下unorder... 目录一、概述二、头文件与命名空间三、常用方法与示例1. 构造与析构2. 迭代器与遍历3. 容量相关4

C++中悬垂引用(Dangling Reference) 的实现

《C++中悬垂引用(DanglingReference)的实现》C++中的悬垂引用指引用绑定的对象被销毁后引用仍存在的情况,会导致访问无效内存,下面就来详细的介绍一下产生的原因以及如何避免,感兴趣... 目录悬垂引用的产生原因1. 引用绑定到局部变量,变量超出作用域后销毁2. 引用绑定到动态分配的对象,对象

C++读写word文档(.docx)DuckX库的使用详解

《C++读写word文档(.docx)DuckX库的使用详解》DuckX是C++库,用于创建/编辑.docx文件,支持读取文档、添加段落/片段、编辑表格,解决中文乱码需更改编码方案,进阶功能含文本替换... 目录一、基本用法1. 读取文档3. 添加段落4. 添加片段3. 编辑表格二、进阶用法1. 文本替换2

PyQt6 键盘事件处理的实现及实例代码

《PyQt6键盘事件处理的实现及实例代码》本文主要介绍了PyQt6键盘事件处理的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起... 目录一、键盘事件处理详解1、核心事件处理器2、事件对象 QKeyEvent3、修饰键处理(1)、修饰键类

C++中处理文本数据char与string的终极对比指南

《C++中处理文本数据char与string的终极对比指南》在C++编程中char和string是两种用于处理字符数据的类型,但它们在使用方式和功能上有显著的不同,:本文主要介绍C++中处理文本数... 目录1. 基本定义与本质2. 内存管理3. 操作与功能4. 性能特点5. 使用场景6. 相互转换核心区别

C++右移运算符的一个小坑及解决

《C++右移运算符的一个小坑及解决》文章指出右移运算符处理负数时左侧补1导致死循环,与除法行为不同,强调需注意补码机制以正确统计二进制1的个数... 目录我遇到了这么一个www.chinasem.cn函数由此可以看到也很好理解总结我遇到了这么一个函数template<typename T>unsigned

SpringBoot+RustFS 实现文件切片极速上传的实例代码

《SpringBoot+RustFS实现文件切片极速上传的实例代码》本文介绍利用SpringBoot和RustFS构建高性能文件切片上传系统,实现大文件秒传、断点续传和分片上传等功能,具有一定的参考... 目录一、为什么选择 RustFS + SpringBoot?二、环境准备与部署2.1 安装 RustF

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

深入解析C++ 中std::map内存管理

《深入解析C++中std::map内存管理》文章详解C++std::map内存管理,指出clear()仅删除元素可能不释放底层内存,建议用swap()与空map交换以彻底释放,针对指针类型需手动de... 目录1️、基本清空std::map2️、使用 swap 彻底释放内存3️、map 中存储指针类型的对象

MySQL的配置文件详解及实例代码

《MySQL的配置文件详解及实例代码》MySQL的配置文件是服务器运行的重要组成部分,用于设置服务器操作的各种参数,下面:本文主要介绍MySQL配置文件的相关资料,文中通过代码介绍的非常详细,需要... 目录前言一、配置文件结构1.[mysqld]2.[client]3.[mysql]4.[mysqldum