【发布时间】:2021-11-23 22:49:14
【问题描述】:
我正在编写一个 C 程序,我想在其中创建一个函数,该函数接受一个“n”整数,并返回它具有的除数。
int divisors(int n) {
int amount = 0;
for(int i = 0; i <= n; i++) {
printf("%d mod %d = %d\n", n, i, n % i);
if(n % i == 0) {
amount++;
}
}
return amount;
}
printf 显然是用于调试的。会导致问题的代码部分是循环从 0 开始,这意味着在第一次迭代中,程序必须打印 N mod 0。但是,我只是通过分配一些 int a 给这个函数来测试这个函数在 main() 中输入 8,程序会打印:
8 mod 0 = 8
8 mod 1 = 0
8 mod 2 = 0
8 mod 3 = 2
8 mod 4 = 0
8 mod 5 = 3
8 mod 6 = 2
8 mod 7 = 1
8 mod 8 = 0
所以 0 模数运行没有问题,而是返回 n。有趣的是,如果我明确告诉程序printf("%d", 8 % 0);,那么我会得到我期望的错误。那么有谁知道为什么 n mod 0 在循环中在 C 中运行时没有错误?
注意:该程序是使用 GCC 编译的,编译时甚至不会抛出任何警告/错误。
编辑:添加 gcc --version。
配置为:--prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/c++/4.2.1 苹果 clang 版本 13.0.0 (clang-1300.0.29.3) 目标:arm64-apple-darwin20.6.0 线程模型:posix 安装目录:/Library/Developer/CommandLineTools/usr/bin
【问题讨论】:
-
这是未定义的行为
-
除以 0 是未定义的行为。 UB 并不意味着程序必须按照您认为应该的方式运行。它可能会崩溃,它可能会产生错误的值,它可能会在任何时候产生“正确”的值或任何其他行为。
-
编译器不够聪明,无法捕捉到问题,因为它不会模拟
i可以获得的所有可能值。所以现在这是一个运行时问题,因为除以 0 最有可能导致异常。 -
另外,编译器是clang,而不是GCC。出于历史原因,
gcc可能是硬链接。请注意,/usr/bin/cc、/usr/bin/gcc和/usr/bin/clang都具有相同的大小和实际上相同的内容。
标签: c function for-loop division modulo