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++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

C++初始化数组的几种常见方法(简单易懂)

《C++初始化数组的几种常见方法(简单易懂)》本文介绍了C++中数组的初始化方法,包括一维数组和二维数组的初始化,以及用new动态初始化数组,在C++11及以上版本中,还提供了使用std::array... 目录1、初始化一维数组1.1、使用列表初始化(推荐方式)1.2、初始化部分列表1.3、使用std::

C++ Primer 多维数组的使用

《C++Primer多维数组的使用》本文主要介绍了多维数组在C++语言中的定义、初始化、下标引用以及使用范围for语句处理多维数组的方法,具有一定的参考价值,感兴趣的可以了解一下... 目录多维数组多维数组的初始化多维数组的下标引用使用范围for语句处理多维数组指针和多维数组多维数组严格来说,C++语言没

前端原生js实现拖拽排课效果实例

《前端原生js实现拖拽排课效果实例》:本文主要介绍如何实现一个简单的课程表拖拽功能,通过HTML、CSS和JavaScript的配合,我们实现了课程项的拖拽、放置和显示功能,文中通过实例代码介绍的... 目录1. 效果展示2. 效果分析2.1 关键点2.2 实现方法3. 代码实现3.1 html部分3.2

c++中std::placeholders的使用方法

《c++中std::placeholders的使用方法》std::placeholders是C++标准库中的一个工具,用于在函数对象绑定时创建占位符,本文就来详细的介绍一下,具有一定的参考价值,感兴... 目录1. 基本概念2. 使用场景3. 示例示例 1:部分参数绑定示例 2:参数重排序4. 注意事项5.

使用C++将处理后的信号保存为PNG和TIFF格式

《使用C++将处理后的信号保存为PNG和TIFF格式》在信号处理领域,我们常常需要将处理结果以图像的形式保存下来,方便后续分析和展示,C++提供了多种库来处理图像数据,本文将介绍如何使用stb_ima... 目录1. PNG格式保存使用stb_imagephp_write库1.1 安装和包含库1.2 代码解

C++实现封装的顺序表的操作与实践

《C++实现封装的顺序表的操作与实践》在程序设计中,顺序表是一种常见的线性数据结构,通常用于存储具有固定顺序的元素,与链表不同,顺序表中的元素是连续存储的,因此访问速度较快,但插入和删除操作的效率可能... 目录一、顺序表的基本概念二、顺序表类的设计1. 顺序表类的成员变量2. 构造函数和析构函数三、顺序表

使用C++实现单链表的操作与实践

《使用C++实现单链表的操作与实践》在程序设计中,链表是一种常见的数据结构,特别是在动态数据管理、频繁插入和删除元素的场景中,链表相比于数组,具有更高的灵活性和高效性,尤其是在需要频繁修改数据结构的应... 目录一、单链表的基本概念二、单链表类的设计1. 节点的定义2. 链表的类定义三、单链表的操作实现四、

数据库使用之union、union all、各种join的用法区别解析

《数据库使用之union、unionall、各种join的用法区别解析》:本文主要介绍SQL中的Union和UnionAll的区别,包括去重与否以及使用时的注意事项,还详细解释了Join关键字,... 目录一、Union 和Union All1、区别:2、注意点:3、具体举例二、Join关键字的区别&php