C/C++ 建议编译选项

警告选项

在程序设计中,我们可能不小心写出一些不合常理的代码语句。大部分情况下,这会使程序行为脱离我们的本意。使编译器发出警告可以在一定程度下规避这种情况。

-Wall

启动常见的警告选项,包括但不限于:

  • 未使用的变量、函数或标签
  • 未初始化的自动变量
  • 格式化字符串不匹配
  • 悬空的控制表达式(if-else 嵌套有歧义)
  • 可能的除零操作
  • 空的循环体
  • 浮点数比较

-Wextra

额外包括一些警告选项,包括但/不限于:

  • 空指针解引用
  • 废弃的函数调用
  • 隐式堕落(switch 忘记 break
  • 可能的未定义行为

没有列举本人认为 OI 中不常用的选项,如“枚举值与整数值的比较”。

-Wformat=2

比上述 -Wall 中包含项更高级别的格式化字符串检查。

-Wpedantic

警告不符合严格标准的代码(编译器可能提供了扩展语法)

例子

例如,编译器可能提供栈空间上的变长数组声明:

{
  int n;
  cin >> n;
  int arr[n];
  ...
}

这在标准中是不被允许的,但可能作为扩展语法。

-Wshadow

警告变量覆盖。

尽管这可能是 C++ 的实用语法之一,但是使用同名变量可能引发不必要的麻烦。

题外话

前几天知道了一个命名空间的古怪语法:

int foo;
int main() {
  int foo;
  cin >> foo >> ::foo;
}

在上述代码中,foo 指代 main 函数内声明的变量,::foo 指代全局作用域内的变量。

栈空间

在 Windows 中,程序栈空间不是无限的,这在调试程序时可能存在麻烦。

使用 -Wl,--stack=2147483647 可以使你的程序栈空间达到 \(2147483647\) 字节,约 \(2\text{GB}\)

其中,-Wl 表示将命令传送到链接器,--stack 是链接器的选项,控制进程栈的大小。

如果是 Linux 系统,在终端使用 ulimit -s unlimited

溢出检查

-ftrapv 选项可以检测整数溢出并导致程序异常终止。

使用 g++ 命令编译时,程序会将操作数保存在寄存器中,调用一个名称类似 __addvsi3 的函数,具体命名与操作符和变量类型有关。经测试,intlong long__int128 都有不同的命名,说明应该都能正常检查。short 运算时没有类似行为,说明不会检查。

使用 clang++ 命令编译时,程序会正常进行运算,然后使用 seto 指令检查溢出标志。不过,由于 short 运算时会使用 l 后缀的指令,不能正常检查。

以上内容来自本地测试,可能与其他环境存在出入。

这同样提醒我们,不要使用 short 类型,除非程序卡空间达到了变态的程度。

不会检查无符号整数溢出,因为后者是良定义的。

posted @ 2024-07-24 13:18  weilycoder  阅读(90)  评论(0编辑  收藏  举报