[C.C++] 【C/C++】C语言工程转C++工程,去除旧代码中的警告和错误

715 0
Honkers 2025-9-29 19:27:07 | 显示全部楼层 |阅读模式

【C/C++】C语言工程转C++工程,去除旧代码中的警告和错误


将老旧的 C语言项目更改为 C++ 项目,目的是方便后期维护,C语言维护成本太高。

零、准备工作

0.1 - 批量修改文件扩展名

Windows 上可以使用命令行 ren 命令,将所有的 .c 文件修改为 .cpp 文件

  1. ren *.c *.cpp
复制代码

Linux 下可以使用 rename 命令

  1. rename 's/\.c/\.cpp/' *
复制代码

0.2 - 使用版本控制系统跟踪

整个过程最好使用版本控制系统 如 SVN 和 Git 跟踪,在产生错误时,能够很方便的回退到前一个版本,或者原始版本。

一、常见警告

存在大量的编译警告,会使得一些 warning 问题存在其中不容易被识别或察觉。

1.1 - 字符串字面值


1.1.1 - 问题分析

C语言中字符串字面值 (string literals) 的类型为 char* 类型,而在 C++ 中为 const char* 类型,因此旧代码中很多的字符串字面值 作为参数传递时,使用编译器 g++ 会产生很多警告,尤其是在 Linux 系统下

问题示例

  1. // function declaration 函数声明
  2. void SetComponentStatus(char * comp, int status);
  3. SetComponentStatus("Device_Name", 3);
  4. // 此处会产生警告
复制代码

警告如下:

  1. warning ISO C++ forbids converting a string constant to 'char *' [-Wwrite-strings]
复制代码
1.1.2 - 修改方法
  1. 修改函数声明和函数体,将 char* 修改为 const char*
  1. void SetComponentStatus(const char * comp, int status);
复制代码
  1. 调用处添加 强转 char*
  1. SetComponentStatus((char*)"Device_Name", 3); // c-style cast
复制代码
  1. 修改编译选项去除 -Wwrite-strings 或添加 -Wno-write-strings

cmake 示例:

  1. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-write-strings")
复制代码

最好的方法当然是 1. 但是会耗费很多时间,为了编译时能够减少警告输出方便定位问题,可以酌情选择 3.

1.2 - register 关键字


1.2.1 - 问题分析

register 这个关键字用于请求编译器尽可能的将变量存在CPU内部寄存器中,而不是通过内存寻址访问,以提高效率优化性能。

此关键字在 C++11 弃用,于 C++17 中删除 (Remove Deprecated Use of the register Keyword) , 现在的编译器比我们更知道应该如何优化。

问题代码示例

  1. register int a;
复制代码

编译报错或警告为:

  1. warning: ISO C++17 does not allow 'register' storage class specifier [-Wregister]
复制代码
1.2.2 - 修改方法
  1. 直接删除 register 关键字
  1. int a; // remove register keyword
复制代码
  1. 使用宏隔离,区分 C++ 的使用标准,把 C++17 与 C++17 以下的区分开。
  1. #if __cplusplus >= 201703L
  2. int a;
  3. #else
  4. register int a;
  5. #endif
复制代码
  1. 修改编译选项去掉 -Wregister 或添加 -Wno-register

cmake 示例

  1. set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-register")
复制代码

注:判断 C++版本的宏以及值

标准__cplusplus 的值
C++ 17201703L
C++ 14201402L
C++ 11201103L

1.2. 同样会面临很大的工作量,可以尝试写脚本批量替换,也会面临隐藏错误的风险,是否可行还要看原来的全量单元测试是否覆盖全面。

二、常见问题

2.1 - 未定义的标识符 extern “C”

引入其他 C语言 方法,使用时会报错,无法解析的外部符号等
C++ 中的编译器为了使用函数重载,声明会编译为区别 C语言编译器的另一种形式

代码示例

  1. extern int AnOldFunction(int a);
  2. void NewFunction()
  3. {
  4. int a = 11;
  5. // call old function
  6. AnOldFunction(a); // 此处会报错
  7. }
复制代码

修改方法

  1. 可以将引入的函数 ,使用 extern “C” 标识
  1. extern "C" int AnOldFunction(int a);
复制代码
  1. 或者将整个头文件,使用 extern “C” 标识
  1. extern "C"
  2. {
  3. #include "OldHeader.h"
  4. }
复制代码
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

中国红客联盟公众号

联系站长QQ:5520533

admin@chnhonker.com
Copyright © 2001-2026 Discuz Team. Powered by Discuz! X3.5 ( 粤ICP备13060014号 )|天天打卡 本站已运行