说明:在此重点介绍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)相关推荐

  1. 指针用作函数参数、指针型函数和函数指针

    指针用作函数参数 以前我们学过的函数参数要么是基本数据类型的变量,要么是类的对象,又或者是数组名,前几讲学到的指针同样可以用作函数参数. 指针作函数形参时,我们调用此函数将实参值传递给形参后,实参和形 ...

  2. 数组元素作为函数参数

    数组元素作为函数参数 数组元素作为函数参数 数组元素作函数实参 数组名作为函数参数 数组元素作为函数参数 数组可以作为函数的参数使用,进行数据传送.数组用作函数参数有两种形式,一种是把数组元素(下标变 ...

  3. 结构体和结构体指针作为函数参数的区别

    0·说明 文章里的观点来自网络的总结,程序经过自己的验证,在VC6.0中可正常执行. 1.测试程序 /* ##结构体指针与结构体变量用作函数参数区别:##结构体指针作为函数参数时,调用时传递的是指向一 ...

  4. c语言数组名做函数的参数传递,【C 语言】数组元素和数组名作为函数参数

    数组用作函数参数有两种形式: 一种是把数组元素(下标变量)作为实参使用: 一种是把数组名作为函数的形参和实参使用. 1.数组元素(下标变量)作为实参使用 数组元素作为函数实参使用与普通变量是完全相同的 ...

  5. C语言学习笔记11-结构体(struct、结构作为函数参数、结构数组)、联合体/共用体typedef; union(大、小端序)

    C语言-结构类型 程序中的数据都需要有类型支撑,当数据很复杂时(不是简单的一个值,如时间信息:年月日时分秒6个数据需要作为一个整体),我们需要声明一个新的结构类型来描述这种复合的数据(可以包含很多不同 ...

  6. python函数定义与参数_Python函数的定义方式与函数参数问题实例分析

    本文实例讲述了Python函数的定义方式与函数参数问题.分享给大家供大家参考,具体如下: 涉及内容: 函数的定义方式 函数的文字描述 空操作语句 位置参数 默认参数 关键参数 可变长度参数 函数的定义 ...

  7. 指针--用指针变量作函数参数的实例(按值调用与模拟按引用调用)、函数指针及其应用

    一.用指针变量作函数参数的实例 思考题: 例题:从键盘输入某班学生某门课成绩(每班人数最多不超过40人,具体人数由键盘输入),是分析下列程序是否能实现计算并输出最高分以及相应学号. #include ...

  8. typescript箭头函数参数_Typescript 入门基础篇(一)

    Typescript 基础 Typescript是Javascript的一个超集.以下typescript简称为ts, 此文章主要是对ts官网文档的一个简化,缩短学习基础时间. 类型基础 ts 的类型 ...

  9. ioctl 函数 参数 详解

    2019独角兽企业重金招聘Python工程师标准>>> ioctl 函数 参数 详解 2009-04-24 11:55 ioctl函数 本函数影响由fd参数引用的一个打开的文件. # ...

最新文章

  1. Java验证(javafx)
  2. 有用的Python模块 - pprint
  3. 软件工程第一次结对编程
  4. 第16届电源技术专题研讨会
  5. 【Elasticsearch】java 客户端 获取 termvectors 词频 统计
  6. python建立sqlite数据库_5分钟快速入门,用Python做SQLite数据库开发,附代码适合初学...
  7. MyCat分布式数据库集群架构工作笔记0010---高可用_Mycat主--从复制配置下
  8. Redis:四、jedis连接redis服务器
  9. 人列计算机 (节选自《三体》作者:刘慈欣)
  10. Matlab实现图像识别(九)
  11. 我们需要“第二人生”吗?[Second life]
  12. 魅族mx4 android5.0,第一手更新 魅族MX4Pro安卓5.0抢先体验
  13. Android 仿微信语音聊天,flutter项目结构
  14. 100天成就卓越领导力:新晋领导者的First100训练法
  15. VS2019:C++程序lib静态库、dll动态库的生成和使用
  16. 从两道基础二分算法题谈check函数的写法
  17. Ubuntu18 + laravel + JavaBridge + 招行国密加解密
  18. “封神台”靶场跑不了爆破,临时解决办法(亲测有效)
  19. 广东省云浮市谷歌卫星地图下载
  20. 无需括号的xss payload

热门文章

  1. decltype specifier
  2. App自动化元素定位技巧__根据 XPATH 定位
  3. android ActionBar介绍
  4. 生态循环水稻种养模式 国稻种芯重庆乡里巴巴功能性育种基地
  5. 实现C++调用C#的动态库dll
  6. easyx能用在Java里面吗_EasyX教程(一)
  7. LeetCode刷题日记 203. 移除链表元素
  8. Fading out siblings on hover in CSS
  9. 谷歌cookie_editor安装教程
  10. 来 COSCon'21 北京线下聚会,将开心开源进行到底!