C++ abs(无符号长)有什么意义吗?
我遇到了这段代码,顺便说一句,我的分析器报告说这是一个瓶颈:C++ abs(无符号长)有什么意义吗?,c++,c,C++,C,我遇到了这段代码,顺便说一句,我的分析器报告说这是一个瓶颈: #include <stdlib.h> unsigned long a, b; // Calculate values for a and b unsigned long c; c = abs(a - b); #包括 无符号长a、b; //计算a和b的值 无符号长c; c=abs(a-b); 这一行是否比c=a-b?这两个选项中是否有一个调用未定义或实现定义的行为,以及是否存在其他潜在的陷阱?请注意,C包含在内,而
#include <stdlib.h>
unsigned long a, b;
// Calculate values for a and b
unsigned long c;
c = abs(a - b);
#包括
无符号长a、b;
//计算a和b的值
无符号长c;
c=abs(a-b);
这一行是否比
c=a-b代码>?这两个选项中是否有一个调用未定义或实现定义的行为,以及是否存在其他潜在的陷阱?请注意,C
包含在内,而不是
不,它没有意义
如果你想要不同,使用
c = (a > b) ? a - b : b - a;
或
如果降到零以下,则无符号将返回(效果类似于添加2sizeof(无符号长)*CHAR_位)
如果您要查找两个数字之间的差异,可以编写一个小模板,如下所示
namespace MyUtils {
template<typename T>
T diff(const T&a, const T&b) {
return (a > b) ? (a - b) : (b - a);
}
}
在C++
(来自cmath
)
如果您注意到,每个函数的参数和返回类型都是有符号的。因此,如果您将一个无符号类型传递给其中一个函数,就会发生隐式转换unsigned T1->signed T2->unsigned T1
(在您的情况下,T1
和T2
可能相同,T1
是long
)。将无符号整数转换为有符号整数时,如果无法在有符号类型中表示该行为,则该行为取决于实现
从4.7积分转换[conv.Integral]
如果目标类型为无符号,则结果值最小
与源整数全等的无符号整数(模2n,其中n为
用于表示无符号类型的位数)。[注:在
二的补语表示法,这种转换是概念上的和逻辑上的
位模式没有变化(如果没有截断)-
结束说明]
如果目标类型是有符号的,则该值将保持不变(如果可以)
以目标类型(和位字段宽度)表示;否则,,
该值由实现定义
我认为当c=a-b是负数时,如果c是无符号数,c不是准确的答案。使用abs来保证c是一个正数。我不知道您是否认为它有意义,但是应用于无符号值的abs()
肯定会返回传入值以外的值。这是因为abs()
接受一个int
参数并返回一个int
值
例如:
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
unsigned u1 = 0x98765432;
printf("u1 = 0x%.8X; abs(u1) = 0x%.8X\n", u1, abs(u1));
unsigned long u2 = 0x9876543201234567UL;
printf("u2 = 0x%.16lX; abs(u2) = 0x%.16lX\n", u2, labs(u2));
return 0;
}
如果设置了无符号值的高位,则abs()
的结果不是传递给函数的值
减法只是分散注意力;如果结果设置了最高有效位,则从abs()
返回的值将不同于传递给它的值
当您用C++头编译此代码,而不是在问题中显示的C标题时,它不能用模糊的调用错误编译:
#include <cstdlib>
#include <iostream>
using namespace std;
int main(void)
{
unsigned u1 = 0x98765432;
cout << "u1 = 0x" << hex << u1 << "; abs(u1) = 0x" << hex << abs(u1) << "\n";
unsigned long u2 = 0x9876543201234567UL;
cout << "u2 = 0x" << hex << u2 << "; abs(u2) = 0x" << hex << abs(u2) << "\n";
return 0;
}
输出:
u1 = 0x98765432; abs(u1) = 0x6789abce
u2 = 0x9876543201234567; abs(u2) = 0x6789abcdfedcba99
<>道德:不要使用C代码头,在C++代码中有C++等价物;使用C++头文件代替.< /P>注意,虽然它对于<代码>未签名的长< /COD>或<代码>未签名的INT/COD>不适用,但它将适用于<代码>未签名的CHAR< <代码>和<代码>未签名的短< /C> >(除了没有人使用的病理系统)。我不知道系统的大小(短)=sisiof(int)。这将比sizeof(int)=sizeof(long)(只是想找个机会来取笑“男人”)
s/sizeof(unsigned long)/sizeof(unsigned long)*CHAR_BIT
@TheParamagneticCroissant谢谢:)的系统要病态得多。因为这些值是无符号的,它们不能是负数,所以abs()
这个电话没有意义。但是,abs()
调用。无法表示值的unsigned到int的潜在转换是未定义的行为。这种转换也是abs产生差异的唯一情况。@UlrichEckhardt如果a=10UL代码>和b=30UL
,正确的答案应该是20UL
,但是去掉abs
会给我错误的答案。在调用abs()
之前,10UL-30UL
产生4294967276UL
(假设为32位无符号长)。如果abs()
按照它的建议(参见我关于宏/重载的说明),结果也是4294967276UL
。如果你想要20,你必须使用有符号算术,例如abs(static\u cast(a)-static\u cast(b))
。你必须确保这不会产生“未定义的行为”。总之,我建议你使用Mohit Jain的建议,即首先检查哪个更大。对于C++的情况,如果你指的是(学校数学)计算自然数,那么“不正确的答案”可能会发生。如果超出了它们的范围,而不是C++,则未签名的值将被包围,所以它总是肯定的。使用<代码> Author()/代码>不应该改变它的值。尽管代码< >代码> >代码>,但是代码< ABS>代码>应该是C++中的一个重载函数。要么实现没有做到这一点,要么abs(int)
不会成为被选中的重载。我认为,如果只包含
,就不会。这只为您提供了标准的C函数。我不知道哪个C++头定义了<代码> Abess()/<代码>的重载。我不知道重载是否包括无符号类型。
被指定为包含C的
声明,除了在命名空间std
中,加上long abs(long)
和long-long abs(long-long)
。C++的
是spe
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
unsigned u1 = 0x98765432;
printf("u1 = 0x%.8X; abs(u1) = 0x%.8X\n", u1, abs(u1));
unsigned long u2 = 0x9876543201234567UL;
printf("u2 = 0x%.16lX; abs(u2) = 0x%.16lX\n", u2, labs(u2));
return 0;
}
u1 = 0x98765432; abs(u1) = 0x6789ABCE
u2 = 0x9876543201234567; abs(u2) = 0x6789ABCDFEDCBA99
#include <cstdlib>
#include <iostream>
using namespace std;
int main(void)
{
unsigned u1 = 0x98765432;
cout << "u1 = 0x" << hex << u1 << "; abs(u1) = 0x" << hex << abs(u1) << "\n";
unsigned long u2 = 0x9876543201234567UL;
cout << "u2 = 0x" << hex << u2 << "; abs(u2) = 0x" << hex << abs(u2) << "\n";
return 0;
}
absuns2.cpp: In function ‘int main()’:
absuns2.cpp:8:72: error: call of overloaded ‘abs(unsigned int&)’ is ambiguous
cout << "u1 = 0x" << hex << u1 << "; abs(u1) = 0x" << hex << abs(u1) << "\n";
^
absuns2.cpp:8:72: note: candidates are:
In file included from /usr/gcc/v4.9.1/include/c++/4.9.1/cstdlib:72:0,
from absuns2.cpp:1:
/usr/include/stdlib.h:129:6: note: int abs(int)
int abs(int) __pure2;
^
In file included from absuns2.cpp:1:0:
/usr/gcc/v4.9.1/include/c++/4.9.1/cstdlib:174:3: note: long long int std::abs(long long int)
abs(long long __x) { return __builtin_llabs (__x); }
^
/usr/gcc/v4.9.1/include/c++/4.9.1/cstdlib:166:3: note: long int std::abs(long int)
abs(long __i) { return __builtin_labs(__i); }
^
absuns2.cpp:10:72: error: call of overloaded ‘abs(long unsigned int&)’ is ambiguous
cout << "u2 = 0x" << hex << u2 << "; abs(u2) = 0x" << hex << abs(u2) << "\n";
^
absuns2.cpp:10:72: note: candidates are:
In file included from /usr/gcc/v4.9.1/include/c++/4.9.1/cstdlib:72:0,
from absuns2.cpp:1:
/usr/include/stdlib.h:129:6: note: int abs(int)
int abs(int) __pure2;
^
In file included from absuns2.cpp:1:0:
/usr/gcc/v4.9.1/include/c++/4.9.1/cstdlib:174:3: note: long long int std::abs(long long int)
abs(long long __x) { return __builtin_llabs (__x); }
^
/usr/gcc/v4.9.1/include/c++/4.9.1/cstdlib:166:3: note: long int std::abs(long int)
abs(long __i) { return __builtin_labs(__i); }
^
#include <cstdlib>
#include <iostream>
using namespace std;
int main(void)
{
unsigned u1 = 0x98765432;
cout << "u1 = 0x" << hex << u1 << "; abs(u1) = 0x" << hex << abs(static_cast<int>(u1)) << "\n";
unsigned long u2 = 0x9876543201234567UL;
cout << "u2 = 0x" << hex << u2 << "; abs(u2) = 0x" << hex << abs(static_cast<long>(u2)) << "\n";
return 0;
}
u1 = 0x98765432; abs(u1) = 0x6789abce
u2 = 0x9876543201234567; abs(u2) = 0x6789abcdfedcba99