使用乘法方法交换数字在 C 中不起作用
最近,我一直在C中进行编码,我试图解决一个数字交换问题。通过使用临时变量,我以更轻松的方式做到了这一点。但是我的教练告诉我使用另一种没有温度变量的方法。这是我的代码:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int a,b,temp;
printf("Enter two numbers: ");
scanf("%d%d",&a,&b);
printf("Entered Numbers:%d,%d \n",a,b);
temp = a; //This method is the easiest one.
a = b;
b = temp;
printf("Numbers are swapped as: %d,%d \n",a,temp);
a = (a*b)/a;
b = (a*b)/b;
printf("Numbers are swapped as: %d,%d",a,b);
return EXIT_SUCCESS;
}
我得到的输出如下:
Enter two numbers: 50 32
Entered Numbers:50,32
Numbers swapped with temp are: 32,50
Numbers swapped without temp are: 50,50
有人可以猜出可能的错误吗?我相信我的数学是对的,但是为什么这样显示呢?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您在第二个逻辑中犯了一个愚蠢的错误,只需替换为提到的一个即可:
You have made a silly mistake in your second logic, just replace with mentioned one:
您在交换代码中犯了一个错误:乘法方法使用3个步骤:
a * b
计算到a
aa
a byb
中的b
,有效地将b
设置为a
的原始值。a
b 纳入a
,有效地将产品除以a
的原始值,因此设置a
到b
的原始值。这种方法的问题在于,它在许多情况下不起作用:
b
为零,则第一部门的行为不确定,在许多情况下,a
为零,则 在许多情况下崩溃了。 ,第二个部门的行为不确定。a * b
超过类型int
的范围,则您的行为也不确定,产生不正确的结果甚至崩溃(尝试交换65536
和65536
)。还有另一种没有临时变量的方法更安全和可靠:您可以XOR数字并再次使用XOR来检索原始值并交换它们,而不是乘以数字并分配产品。
还请注意,您的第三个
printf
语句不正确:您打印temp
而不是b
的值。这是一个修改后的版本:
示例运行而无需优化:
相同的运行效果( clang 或 gcc ):
发生了什么?编译器打破了吗?可以用 goldbolt的编译器资源管理器强>和 GCC 能够识别3种交换方法,并使用4
MOV
指令生成相同的交换代码。由于第三种方法在乘法或划分失败的情况下具有未定义的行为,因此可以产生任何结果,包括预期的结果。一个公然的行为滥用案件。您的讲师应该对这一发现感到惊讶。You made a mistake in the swapping code: the multiplication method uses 3 steps:
a * b
intoa
a
byb
intob
, effectively settingb
to the original value ofa
.a
byb
intoa
, effectively dividing the product by the original value ofa
, hence settinga
to the original value ofb
.The problem with this approach is it does not work for many cases:
b
is zero, the first division has undefined behavior, crashing the program in many casesa
is zero, the second division has undefined behavior.a * b
exceeds the range of typeint
, you also have undefined behavior, producing incorrect results or even a crash (try swapping65536
and65536
).There is another method without a temporary variable the is much safer and reliable: instead of multiplying the numbers and dividing the product, you can xor the numbers and use xor again to retrieve the original values and swap them.
Note also that your third
printf
statement is incorrect: you print the value oftemp
instead ofb
.Here is a modified version:
Sample runs without optimisations:
The same runs with optimisations (clang or gcc):
What is going on? Is the compiler broken? As can be verified with Goldbolt's Compiler Explorer, when optimisations are turned on, both clang and gcc are able to identify the 3 swapping methods and generate the same swapping code with 4
mov
instructions. Since the third method has undefined behavior on cases where the multiplication or division would fail, producing any result is OK, including the expected one. A blatant case of undefined behavior abuse. Your instructor should be amazed at this discovery.