C 语言中的通用 SWAP() 宏

c 语言中的通用 swap() 宏

介绍

c++++ 有 std::swap(),但 c 中没有等效的标准。如果您使用 c23,实现 swap() 是微不足道的:

#define swap(a,b)   do { auto _tmp = (a); (a) = (b); (b) = tmp; } while (0)

有关预处理器宏的更多信息,以及为什么 do … while 是一个特别好的主意,请参阅此处。

这很容易。 那么我们就完成了,对吧? 但是如果您不使用 c23,因此无法使用 auto 怎么办?

c23 之前的 swap()

由于 c23 之前的 c 没有 auto (或 typeof),因此无法声明一个变量是其他变量或表达式的类型。

是的,gcc 和 clang 都支持 __auto_type 和 typeof 作为扩展,你可以根据需要使用它们;但我更喜欢使用标准 c,或者至少有一种方法可以在某些功能不可用时回退到标准 c。

相反,我们可以声明一个大小合适的 char 数组并将其用于临时存储。 当然,我们不能简单地使用 = 来进行赋值,而是必须使用 memcpy():

#define swap(a,b) do {                 char _tmp[ sizeof((a)) ];            memcpy( _tmp, &(a), sizeof((a)) );   (a) = (b);                           memcpy( &(b), _tmp, sizeof((b)) ); } while (0)

您可能认为调用 memcpy() 的效率低于赋值。问题是 memcpy() 有点特殊,因为编译器对其进行了特殊优化 – 足以使生成的代码同样高效。

结盟

上述宏的问题是 _tmp 不能保证 a 类型的对象正确对齐。通常,您可以使用 _alignas,但这在这里不起作用,因为您需要说 _alignas(typeof( a)) 并且我们不能使用 typeof.

即使 _alignas 也可以采用表达式,但您也不能使用 _alignas(a),因为那 not 意味着“与表达式 a 的类型对齐”。相反,它的意思是“与整型常量表达式 a值对齐”——并且由于 a 不是常量表达式,所以它不起作用。

在 c11 和添加 _alignas 之前,创建对齐的 char 数组的常见技巧是将其包含在联合中:

#define swap(a,b) do {                                          union { char buf[ sizeof((a)) ]; max_align_t align; } _tmp;   memcpy( _tmp.buf, &(a), sizeof((a)) );                        (a) = (b);                                                    memcpy( &(b), _tmp.buf, sizeof((b)) ); } while (0)

包含 max_align_t 类型的成员将强制联合(以及其中的 char 数组)针对任何类型正确对齐。

保障措施

我们可以通过至少确保 a 和 b 具有相同的大小来稍微改进 swap() :

#define swap(a,b) do {                                          static_assert( sizeof((a)) == sizeof((b)),                      "swap() arguments must have same size" );                   union { char buf[ sizeof((a)) ]; max_align_t align; } _tmp;   memcpy( _tmp.buf, &(a), sizeof((a)) );                        (a) = (b);                                                    memcpy( &(b), _tmp.buf, sizeof((b)) ); } while (0)

理想情况下,您希望确保 a 和 b 具有相同的 type,而不仅仅是大小,但不幸的是,没有 typeof 就无法做到这一点。

保障c23的swap()

如果您使用 c23,您可以通过确保 a 和 b 具有相同的类型来改进 swap()(因为 typeof 和 typeof_unqual 可用):

#define swap(a,b) do {                              static_assert( is_same( typeof(a), typeof(b) ),     "swap() arguments must have same type" );       auto _tmp = (a); (a) = (b); (b) = _tmp; } while (0)

其中 is_same() 使用 _generic 并且是:

#define IS_SAME(T,U)        _Generic( *(T*)0,           typeof_unqual(U): 1,      default         : 0     )

需要 *(t*)0 将 t(类型)转换为 _generic 所需的表达式。 (提醒:表达式没有被求值,所以它取消引用空指针并不重要。)

typeof_unqual(u) 是删除限定符所必需的,否则如果 u 有限定符,它永远不会匹配。 (提醒:_generic 会丢弃控制表达式类型中的限定符。)

结论

当然 swap() 并不是真正必要的:你总是可以每次都手动打开交换代码;但无论如何,拥有它会让事情变得更好一点。

以上就是C 语言中的通用 SWAP() 宏的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1456805.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月18日 09:08:00
下一篇 2025年12月12日 13:12:57

相关推荐

  • 使用 C++ 框架进行代码重构的难点和方法论

    c++++ 框架代码重构存在复杂性、依赖性、测试覆盖率等难点。方法论包括:逐步方法、测试驱动开发(tdd)、依赖注入(di)、模块化设计。实战案例:qt 应用程序 gui 重构,将传统 qwidget 架构转换为基于 qml 的架构。 使用 C++ 框架进行代码重构的难点和方法论 难点: 大型代码库…

    好文分享 2025年12月18日
    000
  • C++框架与其他编程语言的学习曲线有何不同?

    c++++ 框架的学习曲线比其他编程语言更陡峭,受其复杂性和对硬件的直接访问等因素影响,但具体难度也依个人经验和框架复杂性而异。 C++框架与其他编程语言的学习曲线 学习编程框架就像掌握任何新技能。具体难度取决于个人的经验和特定框架的复杂性。 C++框架 立即学习“C++免费学习笔记(深入)”; C…

    2025年12月18日
    000
  • 如何在 C++ 框架中集成云服务?

    如何将#%#$#%@%@%$#%$#%#%#$%@_4e265749ded663bc++6c021279936cc02e集成到 c++ 框架中:添加云服务:安装 sdk,包含标头文件,实例化云客户端对象。处理云请求:使用多线程或异步编程模型提高并发性。实战案例:将文件上传到 aws s3 存储桶,包…

    2025年12月18日
    000
  • C++框架提供了哪些并发编程机制?

    c++++ 框架提供了三种主要的并发编程机制:1. 线程用于在单独的执行流中运行代码;2. 互斥量用于保护临界区,确保一次只能有一个线程访问;3. 条件变量用于等待特定条件满足。这些机制用于开发可伸缩且高效的并发应用程序,例如 web 服务器、数据库系统和分布式系统。利用 c++ 框架的并发特性,开…

    2025年12月18日
    000
  • C++框架提供了哪些实用程序函数?

    c++++ 框架提供了实用程序函数,主要用于简化常见任务,包括:字符串操作,如查找和替换;算法,如排序和查找最大值;时间管理,如获取时间戳和日期;错误处理,如 try/catch 块;框架特定功能,如日志记录和文件操作。 C++ 框架的实用程序函数 简介 C++ 框架通常提供各种实用程序函数,以简化…

    2025年12月18日
    000
  • C++框架如何通过代码生成提高开发效率?

    在 c++++ 开发中,代码生成技术可显著提高效率,自动生成复杂代码结构,减少冗余和错误,提高一致性,并加快开发。流行的代码生成工具包括 protobuf 和 gcloud,可通过示例流程演示 protobuf 与 grpc 服务的代码生成过程,为应用程序构建提供极大便利,并享受减少开发时间、提高一…

    2025年12月18日
    000
  • C++框架如何支持正则表达式处理?

    c++++ 框架使用库来支持正则表达式处理:libstdc++ regex 库提供了原生支持,包括创建、匹配和替换正则表达式的类和函数。boost.regex 库提供了一个强大而全面的正则表达式库。re2 库是一个由 google 开发的高性能正则表达式库。pcre2 库提供了一个与 perl 兼容…

    2025年12月18日
    000
  • 在 C++ 框架中使用设计模式的常见挑战和最佳实践

    使用设计模式时 c++++ 框架中的常见挑战包括模板元编程、指针和继承层次结构。最佳实践包括谨慎使用模板元编程、优先使用智能指针、编写清晰的接口和避免复杂继承。实战案例展示了工厂方法模式在创造不同类型产品时的应用。 在 C++ 框架中使用设计模式的常见挑战和最佳实践 引言 设计模式是代码重用和软件质…

    2025年12月18日
    000
  • C++ 框架中文档和社区支持的不足及其应对措施

    c++++框架文档和社区支持不足的应对策略包括:文档改善:贡献文档、创建社区文档和提供交互式教程。社区支持增强:建立积极的论坛、吸引开发者参与和创建在线学习社区。 C++ 框架文档和社区支持不足的应对策略 引言 C++ 框架是简化 C++ 开发流程的强大工具,但其文档和社区支持往往不足。这篇文章将探…

    2025年12月18日
    000
  • C++框架在文件操作方面提供了什么功能?

    c++++ 框架提供强大文件操作功能,包括:文件读写(ifstream、ofstream、fstream)文件操纵(seekg、seekp、tellg、tellp、eof)文件状态信息(is_open、good、bad)实战案例:打开文件以读取模式检查文件是否打开成功逐行读取文件关闭文件打开文件以写…

    2025年12月18日
    000
  • C++ 框架中常见性能瓶颈及其优化方法

    常见的 c++++ 框架性能瓶颈包括:内存分配瓶颈:使用内存池分配对象。虚拟函数调用瓶颈:使用非虚方法或替代调度策略。过度使用 stl 容器瓶颈:在关键路径上优先使用原始数组。过度使用锁瓶颈:仅在必要时使用锁。数据序列化瓶颈:使用序列化库或 c++17 特性实现二进制兼容性。 C++ 框架中常见的性…

    2025年12月18日
    000
  • 如何将 C++ 框架与 Rust 集成?

    在现代软件开发中,rust 可与 c++++ 框架集成,以充分利用 rust 的安全性和性能优势:设置 rust 编译器和 cargo 包管理器。创建一个 rust 项目。准备 c++ 框架,确保提供了 rust 绑定。在 rust 代码中使用 extern 块声明 c++ 函数和类。在 rust …

    2025年12月18日
    000
  • C++框架如何增强异常处理能力?

    c++++ 中提升异常处理能力的框架提供了以下优势:使用 boost.exception,可定义自定义异常类、异常跟踪和异常过滤功能。libstdc++ 的异常类型可用于根据异常类型采取适当的处理措施。使用 doxygen,可记录自定义异常和框架异常的详细信息,以增强代码可读性和可维护性。 使用 C…

    2025年12月18日
    000
  • C++框架中集成了哪些测试工具?

    c++++ 框架集成的测试工具包含:单元测试框架(如 boost.test)集成测试框架(如 catch2)mock 对象框架(如 google mock)性能分析工具(如 google benchmark)覆盖率工具(如 gcov)这些工具能帮助开发者高效编写和执行测试用例,提高代码质量。 C++…

    2025年12月18日
    000
  • C++ 框架中部署和维护的常见挑战及最佳做法

    部署 c++++ 应用程序的常见挑战包括:依赖关系管理环境差异二进制兼容性手动安装和更新最佳实践包括:自动化部署流程使用包管理器容器化应用程序使用配置文件实施持续集成与测试使用版本控制错误监控性能分析 C++ 框架中部署和维护的常见挑战及最佳做法 部署常见挑战 依赖管理:管理库及其依赖项是部署 C+…

    2025年12月18日
    000
  • 在 C++ 框架中处理并发和多线程的挑战

    并发和多线程在 c++++ 中的挑战数据竞态条件: 使用互斥锁或原子变量同步共享数据访问。死锁: 使用锁顺序,按相同顺序锁定共享资源。性能开销: 调整线程数量或使用轻量级同步机制来优化性能。 在 C++ 框架中处理并发和多线程的挑战 并发和多线程是构建现代 C++ 应用程序的两个基本方面,但它们也带…

    2025年12月18日
    000
  • 如何将C++框架与嵌入式系统集成?

    将c++++框架与嵌入式系统集成:选择合适的c++框架(如qt、arduino、zephyr)。配置构建系统(makefile或cmake)。将框架与嵌入式代码集成(使用合适的头文件和库)。处理中断和线程(嵌入式系统中必不可少)。通过遵循这些步骤,可以使用c++框架显著提高嵌入式系统开发的效率和灵活…

    2025年12月18日
    000
  • 如何使用适配器或桥接器将 C++ 框架与其他系统连接

    在大型软件项目中,适配器模式可将现有类封装到新接口中,使之兼容客户端代码;桥接器模式将抽象层与实现层分离,实现独立修改。 使用适配器或桥接器将 C++ 框架与其他系统连接 在大型软件项目中,不同的系统或服务可能采用不同的编程语言或接口编写。将这些系统集成到单个应用程序中时,需要一种机制来连接它们。适…

    2025年12月18日
    000
  • 使用 C++ 框架进行复杂集成的设计模式

    c++++框架中用来简化复杂集成的设计模式包括:单一责任原则:将每个组件限制为一项单一任务。facade:抽象多个组件为一个单一接口,隐藏底层复杂性。依赖反转原则:反转依赖关系,提高可扩展性和可维护性。组合模式:通过重用现有对象而不是继承来创建新对象。 使用 C++ 框架进行复杂集成的设计模式 在现…

    2025年12月18日
    000
  • 如何将 C++ 框架与不同平台集成

    可以通过以下步骤将 c++++ 框架与不同平台集成:windows:使用 visual studio 将框架添加到项目中。linux:使用 cmake 将框架添加到项目中。web:在 web 应用程序中编写代码并将其与框架链接。 如何将 C++ 框架与不同平台集成 随着 C++ 框架变得越来越流行,…

    2025年12月18日
    000

发表回复

登录后才能评论
关注微信