一些容易被忽略的 C 与 C++ 的重要区别
头文件
C 标准库头文件名在 C++ 中通常去除扩展名,并加上 c 前缀,如:
- stdio.h -> cstdio
- stdlib.h -> cstdlib
其中一个重要的区别是后者保证与 C 库兼容的各个函数名可以在 std 命名空间中找到,但并不保证它们不存在于根命名空间中,这可能会引发一些难以发现的 bug。
/*
* abs.cpp - 求绝对值的小程序
*
* 该代码有一处较为隐蔽的 bug,请尽力找出它!
*/
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cerrno>
int main(int argc, char *argv[])
{
if(argc == 1) { // 校验输入命令行参数
fprintf(stderr,
"usage: %s <numbers>\n", program_invocation_short_name);
exit(EXIT_FAILURE);
}
for(int i = 1; i < argc; ++i) { // 对每个参数,输出运算结果
char *endp;
double num = strtod(argv[i], &endp);
if(*endp) { // 没有读到字符串结尾,说明出现了错误
fprintf(stderr, "ERROR: invalid number: %s", argv[i]);
}
num = abs(num); // 计算绝对值
printf("%lf\n", num);
}
return 0; // 此处始终退回成功值,不是 bug
}
不幸地是,上面的代码顺利通过了编译,且 GCC 发出没有任何警告。
结合输出结果便更容易发现这个 bug!
lyazj@HelloWorld:~$ g++ --version
g++ (Ubuntu 11.3.0-1ubuntu1~22.04.1) 11.3.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
lyazj@HelloWorld:~$ g++ -Wall -Wshadow -Wextra abs.cpp -o abs
lyazj@HelloWorld:~$ ./abs
usage: abs <numbers>
lyazj@HelloWorld:~$ ./abs 0 1 -1 1.5 -1.5
0.000000
1.000000
1.000000
1.000000
1.000000