【问题标题】:cpp using abs() function with size_tcpp 使用带有 size_t 的 abs() 函数
【发布时间】:2018-10-09 01:04:10
【问题描述】:

我正在尝试检查两个字符是否是较大字符串中的邻居,但无法检查它们索引中差异的绝对值。以下是我的代码:

string state_string = "012345";
string goal_state_string = "125430";
for (int i = 0; i < state_string.length() - 1; i++)
{
    cout << abs(goal_state_string.find(state_string[i]) - goal_state_string.find(state_string[i + 1])) << endl;
}

当我运行时,我得到以下输出:

$ make test
g++ -std=c++11 test.cpp
test.cpp: In function ‘int main()’:
test.cpp:107:106: error: call of overloaded ‘abs(std::basic_string<char>::size_type)’ is ambiguous
         cout << abs(goal_state_string.find(state_string[i]) - goal_state_string.find(state_string[i + 1])) << endl;
                                                                                                          ^
In file included from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/cstdlib:75:0,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/ext/string_conversions.h:41,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/basic_string.h:6349,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/string:52,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/locale_classes.h:40,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/ios_base.h:41,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/ios:42,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/ostream:38,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/iostream:39,
                 from test.cpp:1:
/usr/include/stdlib.h:70:5: note: candidate: int abs(int)
 int abs (int);
     ^~~
In file included from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/cstdlib:77:0,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/ext/string_conversions.h:41,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/basic_string.h:6349,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/string:52,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/locale_classes.h:40,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/ios_base.h:41,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/ios:42,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/ostream:38,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/iostream:39,
                 from test.cpp:1:
/usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/std_abs.h:56:3: note: candidate: long int std::abs(long int)
   abs(long __i) { return __builtin_labs(__i); }
   ^~~
/usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/std_abs.h:61:3: note: candidate: long long int std::abs(long long int)
   abs(long long __x) { return __builtin_llabs (__x); }
   ^~~
/usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/std_abs.h:70:3: note: candidate: constexpr double std::abs(double)
   abs(double __x)
   ^~~
/usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/std_abs.h:74:3: note: candidate: constexpr float std::abs(float)
   abs(float __x)
   ^~~
/usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/std_abs.h:78:3: note: candidate: constexpr long double std::abs(long double)
   abs(long double __x)
   ^~~
make: *** [Makefile:37: test] Error 1

hp user@DESKTOP-PGC8V9D /cygdrive/e/Google Drive/Phd_git/psvn/core/lessons/A-star
$ make test
g++ -std=c++11 test.cpp
test.cpp: In function ‘int main()’:
test.cpp:13:106: error: call of overloaded ‘abs(std::basic_string<char>::size_type)’ is ambiguous
         cout << abs(goal_state_string.find(state_string[i]) - goal_state_string.find(state_string[i + 1])) << endl;
                                                                                                          ^
In file included from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/cstdlib:75:0,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/ext/string_conversions.h:41,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/basic_string.h:6349,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/string:52,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/locale_classes.h:40,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/ios_base.h:41,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/ios:42,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/ostream:38,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/iostream:39,
                 from test.cpp:1:
/usr/include/stdlib.h:70:5: note: candidate: int abs(int)
 int abs (int);
     ^~~
In file included from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/cstdlib:77:0,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/ext/string_conversions.h:41,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/basic_string.h:6349,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/string:52,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/locale_classes.h:40,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/ios_base.h:41,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/ios:42,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/ostream:38,
                 from /usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/iostream:39,
                 from test.cpp:1:
/usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/std_abs.h:56:3: note: candidate: long int std::abs(long int)
   abs(long __i) { return __builtin_labs(__i); }
   ^~~
/usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/std_abs.h:61:3: note: candidate: long long int std::abs(long long int)
   abs(long long __x) { return __builtin_llabs (__x); }
   ^~~
/usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/std_abs.h:70:3: note: candidate: constexpr double std::abs(double)
   abs(double __x)
   ^~~
/usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/std_abs.h:74:3: note: candidate: constexpr float std::abs(float)
   abs(float __x)
   ^~~
/usr/lib/gcc/x86_64-pc-cygwin/7.3.0/include/c++/bits/std_abs.h:78:3: note: candidate: constexpr long double std::abs(long double)
   abs(long double __x)
   ^~~
make: *** [Makefile:37: test] Error 1

我的问题如下:

  1. 不应发现 find 函数返回某种整数类型,即。一个无符号整数,如果是这样,为什么不呢。有什么意义 拥有这种似乎对大多数人不起作用的替代类型 它应该调用哪个函数?
  2. 使用此类型/避免此问题时的最佳做法是什么?我应该将其转换为 int 吗?

【问题讨论】:

  • 正如您在编译器输出中看到的,abs 是为签名类型定义的。 std::string::size_type 未签名。要正确找到两个无符号值之间的距离,首先确定其中一个最大,然后从中减去另一个。
  • 我之前已经发布了一个答案,但我现在看到你的方法的主要警告是,如果find 无法检索到搜索的字符串,它会返回std::string::npos,即-1,那对于无符号值意味着最大的可表示值。一旦你处理了这个问题,你就可以在这个 code review's post 中找到如何区分两个无符号整数

标签: c++


【解决方案1】:

要了解abs是做什么的,我们必须了解signedunsigned类型之间的区别。

考虑以下语句:

a = 10
b = -20
c = a + b

c 的结果是否取决于 a,b,c 是有符号还是无符号?

令人惊讶的是它没有。因为计算机使用二进制补码处理数字,所以如果两个数字相隔 2^N,则认为它们是同一个数字。

不仅add,subtract不关心符号,multiplication也不关心符号:

x*(2^N - y) = x*2^N - x*(-y) = x*(-y) mod 2^N

由于这种影响,有符号数和无符号数之间的限制被放宽了。

更多细节可以在X86架构的指令集中找到。实际上 X86 定义了一个统一加法,它同时处理有符号和无符号加法,有符号和无符号加法的唯一区别是载波位(也称为上溢/下溢位)。

有些运营商确实关心符号。喜欢

  1. 打印。人们肯定更喜欢 -1 而不是 4294967295,所以 printf 将有符号和无符号“%u”的符号分开
  2. 比较。 4294967295 > 0,但 -1
  3. abs 函数
  4. 还有更多...

在使用关心符号的运算符时,您最好更加小心。这就是为什么abs 不允许带无符号参数的原因。

【讨论】:

  • 现在我从来没有做过一个不需要的目标,但是 C++ 不需要对有符号整数进行补码。它只是该问题最常用的解决方案。
  • 实际上将无符号值放入 abs 是没有意义的。因为它之后总是一样的,因为它是积极的。就像@user4581301 指出的溢出是未定义的行为,即使目标平台将其实现为二进制补码。编译器不必遵守,可以优化奇怪的东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-11
  • 2023-02-17
  • 2012-11-07
  • 1970-01-01
相关资源
最近更新 更多