两个为 true 的变量在 (tmp1 == tmp2) 中返回 false.为什么
Two variables that are true return false in (tmp1 == tmp2). Why?
我刚刚遇到了一个问题。我想比较一下我的埃拉托斯特尼斯筛子是否包含质数。在代码中我有这一行
if (sieve[2] == is_prime(2)) // returns false
printf ("true");
现在,sieve[2] 是一个布尔值,它的值是真的(我什至检查了数组,所以毫无疑问(。 is_prime(2( 也是一个布尔值(我也检查过(。
现在我的问题。上面显示的行返回 false。是的 - 即使它的语句是:
if ( true == true ) // which normally returns true
printf ("true");
但是,在删除一个等式符号后:
if ( sieve[2] = is_prime(2) ) // returns true
printf ("true");
此语句返回 true。
有人可以简要解释一下在这种情况下,与==相比,一个方程标记是如何工作的吗?
提前致谢
编辑
is_prime:
bool is_prime(int x) {
unsigned int i,j,k;
if (x < 2) return false;
else {
for (i=2; i!=x; i++) {
if (x == i) return true;
else if (x % i == 0) return false;
}
}
}
筛:
const int n = 10000;
bool sieve[n+1];
.
.
unsigned long int i;
sieve[0] = sieve[1] = false;
for (i=2; i<=n; i++) sieve[i] = true;
for (i=2; i*i<=n; i++) {
if (sieve[i]) {
unsigned tmp = 2*i;
while (tmp <= n) {
sieve[tmp] = false;
tmp += i;
}
}
}
[编辑2]问题出在"is_prime(x("上 将循环条件从"i!=x"更改为"i<=x"很抱歉给您带来麻烦,并感谢您的回答
更新
bool is_prime(int x) {
unsigned int i,j,k;
if (x < 2) return false;
else {
for (i=2; i!=x; i++) {
if (x == i) return true;
else if (x % i == 0) return false;
}
}
}
您的is_prime()
(上图(被破坏,具有未定义的行为,例如当x
被2
(或任何实际的素数(时,它会在没有return
语句的情况下到达函数的末尾 - i!=x
测试意味着循环内的x == i
永远不会true
。
is_prime(2)
它可能会返回有效的随机结果(基于剩余的堆栈或寄存器内容/在您记录的输出中,它似乎x
本身"返回",大概是因为您的 ABI 使用相同的 CPU 寄存器或堆栈地址传入参数并传回函数的返回值(。
具体来说对于 2,流进入第一个 else
子句,然后i=2
第一个i!=x
测试失败,for
循环立即退出......在for
的范围之后没有return
。 最小更正的代码(可以实现更快的实现,但保持简单性和预期的逻辑(:
bool is_prime(int x)
{
if (x < 2) return false;
for (int i = 2; i < x; ++i)
if (x % i == 0)
return false;
return true;
}
等效性/==
使用 sieve[2] == is_prime(2)
它会检查它们具有相同的值 - 可能在转换其中一个值以启用比较之后,但您说它们都是布尔值,所以没有必要。 这将在if
都true
或都false
时产生"true"值。
现在我的问题。上面显示的行返回 false。是的 - 即使它返回 false...
这没有任何意义...我建议您在 if
语句之前添加以下内容以检查变量的值:
std::cout << "sieve[2] " << sieve[2] << " (bool)" << (bool)sieve[2]
<< ", is_prime(2) " << is_prime(2) << std::endl;
我什至签入了数组,所以毫无疑问
警惕错误,例如看到数组内容显示 ala { true false true false } 并认为[2]
是第二个值......它实际上是第三个。因为数组索引从 0 开始。
分配/=
使用sieve[2] = is_prime(2)
,您将is_prime(2)
的值分配给sieve[2]
,并且如果该值在布尔上下文中被视为为真,则if
语句被视为"true"(即它是值为true
的布尔值,或非0数字或指针等(。 对于大多数数据类型,if (sieve[2] = is_prime(2)) ...
的执行流程与简单的if (is_prime(2)) ...
相同,但当然它也修改了sieve[2]
。
它将右侧操作数分配给左侧操作数,并返回左侧操作数。由于您正在为变量赋值 true,因此它的计算结果为 true。如果将变量设置为 false
,则不会获得输出,例如:
bool x;
if(x = false)
printf("this won't be printed");
在这里,等于影响左运算符与右运算符的值,然后测试该值。因此,结果必须是正确运算符的值。
is_prime
中的循环永远不会运行检查x == i
为真,因为它运行的时间只要 x != i
.这两个条件是相互排斥的。
这意味着函数将在没有 return
语句的情况下结束,这会导致未定义的行为。
if ( sieve[2] = is_prime(2) )
包含作业,而不是比较。
由于赋值的值是分配的值,因此无论何时is_prime(2)
都是如此。
但是,让我们看看您的is_prime
,看看如果我们将其传递2
会发生什么......
bool is_prime(int x) {
unsigned int i,j,k;
到目前为止,一切顺利,但j
和k
从未使用过,所以它们不应该真的在这里。
if (x < 2) return false;
2 不小于 2,所以我们将继续...
else {
for (i=2; i!=x; i++) {
好的,设置i = 2
,并将其与x
进行比较,这是2
,并且......哎呀,i
等于x
,所以我们立即放弃循环...
if (x == i) return true;
else if (x % i == 0) return false;
}
}
。然后在这里失败,我们没有像我们承诺的那样返回值,并导致未定义的行为。
}
所以,你的程序是未定义的(你真的应该打开编译器警告,或者开始侦听它们(。
这发生在每个素数上。
你可以像这样重写循环:
for (i=2; i <= x; i++) {
if (x == i) return true;
else if (x % i == 0) return false;
}
或
for (i=2; i < x; i++) {
if (x % i == 0) return false;
}
return true;
为什么if (is_prime(2))
似乎有效?
(由于此代码未定义,因此以下内容主要是推测,应仅使用适当的盐量来执行。
通常,当一个函数应该返回一些东西但没有返回时,调用函数将只获取存储在返回值应该在的位置的任何内容并使用它。
在这种情况下,这个值很可能与表示true
的位模式不同,因此将比较不等于true
,在if (is_prime(2) == true)
。
但是,它也很可能不是表示false
的位模式,因此在有条件的if(is_prime(2))
中将被视为true
。
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- 什么时候在C++中返回常量引用是个好主意
- 你能重载对象变量名本身返回的内容吗
- 为什么 Serial.println(<char[]>);返回随机字符?
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- 如何获取std::result_of函数的返回类型
- QueryWorkingSet总是返回false
- (C++)分析树以计算返回错误值的简单算术表达式
- 访问者访问变体并返回不同类型时出错
- 如何返回一个类的两个对象相加的结果
- OpenInventor从9.8升级到10.4.2后,GLSL纹理返回零
- lower_bound()返回最后一个元素
- "throw expression code" 1e7 >返回 d 是什么?投掷标准::overflow_error( "too big" ) : d;意味 着?
- 奇怪的(对我来说)返回声明 - 在谷歌上找不到任何关于它的信息
- 如何取消对nullptr的屏蔽,返回正确的对象
- 奇怪的结构&GCC&clang(void*返回类型)
- 架构决策:返回std::future还是提供回调
- 从python中调用C++函数并获取返回值
- 矩阵向量乘法(cublasDgemv)返回零
- 两个为 true 的变量在 (tmp1 == tmp2) 中返回 false.为什么