本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《
阿里云开发者社区用户服务协议
》和
《
阿里云开发者社区知识产权保护指引
》。如果您发现本社区中有涉嫌抄袭的内容,填写
侵权投诉表单
进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
整个过程最好使用版本控制系统 如 SVN 和 Git 跟踪,在产生错误时,能够很方便的回退到前一个版本,或者原始版本。
一、常见警告
存在大量的编译警告,会使得一些 warning 问题存在其中不容易被识别或察觉。
1.1 - 字符串字面值
1.1.1 - 问题分析
C语言中
字符串字面值
(string literals) 的类型为
char*
类型,而在 C++ 中为
const char*
类型,因此旧代码中很多的字符串字面值 作为参数传递时,使用编译器
g++
会产生很多警告,尤其是在 Linux 系统下
void SetComponentStatus(char * comp, int status);
SetComponentStatus("Device_Name", 3);
警告如下:
warning ISO C++ forbids converting a string constant to 'char *' [-Wwrite-strings]
1.1.2 - 修改方法
- 修改函数声明和函数体,将
char*
修改为 const char*
void SetComponentStatus(const char * comp, int status);
调用处添加 强转 char*
SetComponentStatus((char*)"Device_Name", 3);
修改编译选项去除 -Wwrite-strings 或添加 -Wno-write-strings
cmake 示例:
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) , 现在的编译器比我们更知道应该如何优化。
问题代码示例
register int a;
编译报错或警告为:
warning: ISO C++17 does not allow 'register' storage class specifier [-Wregister]
1.2.2 - 修改方法
- 直接删除 register 关键字
int a;
使用宏隔离,区分 C++ 的使用标准,把 C++17 与 C++17 以下的区分开。#if __cplusplus >= 201703L
int a;
#else
register int a;
#endif
修改编译选项去掉 -Wregister 或添加 -Wno-register
cmake 示例
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-register")
注:判断 C++版本的宏以及值
标准 | __cplusplus 的值 |
---|
C++ 17 | 201703L |
C++ 14 | 201402L |
C++ 11 | 201103L |
1. 和 2. 同样会面临很大的工作量,可以尝试写脚本批量替换,也会面临隐藏错误的风险,是否可行还要看原来的全量单元测试是否覆盖全面。
二、常见问题
2.1 - 未定义的标识符 extern "C"
引入其他 C语言 方法,使用时会报错,无法解析的外部符号等
C++ 中的编译器为了使用函数重载,声明会编译为区别 C语言编译器的另一种形式
extern int AnOldFunction(int a);
void NewFunction()
int a = 11;
AnOldFunction(a);
- 可以将引入的函数 ,使用 extern "C" 标识
extern "C" int AnOldFunction(int a);
或者将整个头文件,使用 extern "C" 标识extern "C"
#include "OldHeader.h"