当前位置: 首页> 科技> 互联网 > 国家防疫新十条政策_商城网站建设哪家便宜_品牌推广的具体方法_百度广告位价格表

国家防疫新十条政策_商城网站建设哪家便宜_品牌推广的具体方法_百度广告位价格表

时间:2025/7/12 3:08:49来源:https://blog.csdn.net/arong_xu/article/details/146399553 浏览次数:1次
国家防疫新十条政策_商城网站建设哪家便宜_品牌推广的具体方法_百度广告位价格表

开始之前

安装 clang-tidy-21

本文所用样例需要 clang tidy 21 以上版本, 就目前(2025 年 3 月 20)来说, 这个版本是比较新的, 如果要按照请参考: https://apt.llvm.org/

wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 21
sudo apt install clang-tidy-21

文中的示例源码可以在此处访问.

背景

在 C++20 之前, 我们使用 printf系列函数来打印日志, printf 是一个非常方便的函数, 但是它有很多问题, 比如:

  1. 类型安全问题: printf 不会检查格式化字符串与参数类型的匹配性. 如果格式说明符和参数类型不一致, 可能会导致未定义行为或运行时错误.

    #include <cstdio>int main() {printf("%d", "hello");
    }
    
  2. 跨平台问题: 由于不同系统对于类型的宽度不同, 可能导致你需要在不同平台使用不同的说明符.

    类型32 位 Linux64 位 Linux32/64 位 Windows
    long位数32 bit64 bit32 bit
    long"%ld""%ld""%ld"
    int64_t"%lld""%ld""%lld"
  3. 缓冲区溢出问题: 使用 sprintf 容易引发缓冲区溢出等问题, 尤其是在处理字符串时.

  4. 缺乏扩展性: printf 无法直接支持用户自定义类型的格式化输出. 需要额外编写代码来处理自定义类型.

clang tidy

Clang tidy 是一个静态分析工具, 它可以检查 C++ 代码中的问题, 并建议修复它们. 它提供了许多内置的规则, 可以用于检查 printf 函数的使用.

Clang-tidy 是一个独立的工具, 并不与 Clang 绑定. 你可以用 Clang-tidy 来检查你的代码, 但是生成环境用 GCC 或者其他编译器编译代码.

Clang-tidy 提供了一个名为 modernize-use-format 的规则(版本要求应该是 21), 可以检查 printf 函数的使用, 并建议使用 std::format 替代它.

适用场景

  1. printf -> std::print(或者fmt::print)

    printf("Hello %s\n", "world!");
    

    会被转为

    std::println("Hello {}", "world!");
    
  2. absl::StrFormat -> std::format(或者fmt::format)

    auto s = absl::StrFormat("Hello %s", "world!");
    

    替换为

    auto s = std::format("Hello {}", "world!");
    
  3. 类似下面生成一个新字符串的函数

    std::string strformat(const char* fmt, ...);
    auto s = strformat("Hello {}", "world!");
    

    可以替换为(需要增加配置)

    auto s = std::format("Hello {}", "world!");
    

如何集成

示例项目地址
我们需要如下的配置

  1. 配置 .clang-tidy 文件
  2. 生成编译数据库 compile_commands.json

.clang-tidy 文件配置可以参考:

如果你想使用std::print/std::println/std::format, 那么这样配置即可

Checks: modernize-use-std-format,modernize-use-std-print
HeaderFilterRegex: .*
CheckOptions:modernize-use-std-format.StrFormatLikeFunctions: strprintf

如果想使用libfmt, 那么需要这样配置:

Checks: modernize-use-std-print,modernize-use-std-format
HeaderFilterRegex: .*
CheckOptions:modernize-use-std-print.PrintHeader: <fmt/core.h>modernize-use-std-print.PrintfLikeFunctions: printfmodernize-use-std-print.ReplacementPrintFunction: fmt::printmodernize-use-std-print.ReplacementPrintlnFunction: fmt::printlnmodernize-use-std-format.FormatHeader: <fmt/core.h>modernize-use-std-format.StrFormatLikeFunctions: strprintfmodernize-use-std-format.ReplacementFormatFunction: fmt::format

CMake 集成

cmake_minimum_required(VERSION 3.28)
project(replace-printf)# 启用编译数据库生成
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)# 启用 clang-tidy
find_program(CLANG_TIDY_PATH NAMES clang-tidy-21)
if(CLANG_TIDY_PATH)# 增加 --fix 修复选项set(CMAKE_CXX_CLANG_TIDY ${CLANG_TIDY_PATH} --fix)
else()message(FATAL_ERROR "clang-tidy not found")
endif()# add an option to use fmt library
find_package(fmt REQUIRED)add_executable(sample test.cpp)
target_link_libraries(sample PRIVATE fmt::fmt)

Makefile 集成

fix: checkclang-tidy-21 test.cpp --fix -p ./compile_commands.json
check:clang-tidy-21 --list-checks -checks="modernize-*" | grep -q "modernize-use-std-format" || { echo "No match found"; exit 1; }

测试结果

#include <stdio.h>#include <cstdarg>
#include <cstdio>
#include <string>extern std::string strprintf(const char *fmt, ...);void foo() {char buffer[100];int a = 10;float b = 3.14;char str[] = "Hello";// 使用 sprintf 格式化字符串sprintf(buffer, "Integer: %d, Float: %.2f, String: %s", a, b, str);// 输出结果printf("Formatted string: %s\n", buffer);
}int main(int argc, char *argv[]) {if (argc == 1) {fprintf(stderr, "Usage:\n\t%s  <arg>\n", argv[0]);return -1;}// printf->std::print with modernize-use-std-printprintf("Hello %s\n", argv[1]);puts(strprintf("Hello %s", argv[1]).c_str());
}

使用 libfmt 转换得到的结果

#include <fmt/core.h>
#include <fmt/core.h>
#include <stdio.h>#include <cstdarg>
#include <cstdio>
#include <string>extern std::string strprintf(const char *fmt, ...);void foo() {char buffer[100];int a = 10;float b = 3.14;char str[] = "Hello";// 使用 sprintf 格式化字符串sprintf(buffer, "Integer: %d, Float: %.2f, String: %s", a, b, str);// 输出结果fmt::println("Formatted string: {}", buffer);
}int main(int argc, char *argv[]) {if (argc == 1) {fprintf(stderr, "Usage:\n\t%s  <arg>\n", argv[0]);return -1;}// printf->std::print with modernize-use-std-printfmt::println("Hello {}", argv[1]);puts(fmt::format("Hello {}", argv[1]).c_str());
}

内部原理

这个功能的开发者在视频中介绍了相关的实现原理. 有兴趣的读者可以看视频和源码:

  1. Customising clang tidy to modernise your legacy C++ code - Mike Crowe

  2. https://github.com/llvm/llvm-project/

    • clang-tools-extra/clang-tidy/utils/FormatStringConverter.cpp
    • clang-tools-extra/clang-tidy/modernize/UseStdFormat.cpp
    • clang-tools-extra/test/clang-tidy/checkers/modernize/use-std-format.cpp

参考资料

  • Customising clang tidy to modernise your legacy C++ code - Mike Crowe - Meeting C++ 2024
  • Clang Tidy - LLVM
  • modernize-use-std-format
  • modernize-use-std-print
  • LLVM Debian/Ubuntu nightly packages

相关阅读

  • C++23 格式化输出新特性详解: std::print 和 std::println
  • C++ libfmt 实战: 高效简便的格式化库
关键字:国家防疫新十条政策_商城网站建设哪家便宜_品牌推广的具体方法_百度广告位价格表

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: