функции stroll, strol не выдают правильный вывод для long_min - PullRequest
0 голосов
/ 14 апреля 2020

Для следующего кода

#include <bits/stdc++.h>
using namespace std;
int main()
{
   bitset<64>b(numeric_limits<long>::min());
   string s=b.to_string();
   char *ptr=new char [s.size()+1];
   strcpy(ptr,s.c_str());
   long l1=strtol(ptr,NULL,2);
   cout<<"l1= "<<l1<<endl;
  long l2=strtoul(ptr,NULL,2);
   cout<<"l2= "<<l2<<endl;
   cout<<strtoul(ptr,NULL,2)<<endl;
}

Вывод

l1= 9223372036854775807
l2= -9223372036854775808
9223372036854775808

Почему l1 не long_min и почему l2? Я читал, что строка может содержать знак + / - в начале для функций ato *, strto *. Но отрицательные числа в двоичном коде не имеют знака - в дополнении 2, которое использует компьютер. Я в замешательстве.

Ответы [ 2 ]

1 голос
/ 14 апреля 2020

Значение unsigned long int

9223372036854775808

, выводимое этим оператором

cout<<strtoul(ptr,NULL,2)<<endl;

, не может быть представлено в объекте типа signed long int.

В этом операторе

long l1=strtol(ptr,NULL,2);

, поскольку значение не представляется в типе signed long int, функция strtol возвращает LONG_MAX (поскольку в строке нет знака минус). И это значение выводится этим оператором

cout<<"l1= "<<l1<<endl;

из стандарта C (7.22.1.4 Функции strtol, strtoll, strtoul и strtoull)

8 Strtol Функции strtoll, strtoul и strtoull возвращают преобразованное значение, если оно есть. Если преобразование не может быть выполнено, возвращается ноль. Если правильное значение находится за пределами диапазона представимых значений, возвращается LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX, ULONG_MAX или ULLONG_MAX (в соответствии с типом и знаком возвращаемого значения, если они есть), и значение макроса ERANGE хранится в errno.

Однако значение представляется в виде unsigned long int. Таким образом, этот вызов функции strtoul возвращает правильное значение

long l2=strtoul(ptr,NULL,2);

, но значение присваивается объекту типа signed long int. Таким образом, его наиболее значимый бит интерпретируется как знаковый бит, а следующий оператор

cout<<"l2= "<<l2<<endl;

выводит значение LONG_MIN.

1 голос
/ 14 апреля 2020

Вы получаете ошибку ERANGE для предоставления положительного значения, превышающего то, что может удерживать long. Чтобы он работал с strtol, вам нужно добавить -:

#include <bitset>
#include <cstring>
#include <iostream>
#include <limits>
#include <string>

int main()
{
   std::bitset<64> b(std::numeric_limits<long>::min());

   std::string s = "-" + b.to_string();

   long l1=strtol(s.c_str(), NULL, 2);
   std::cout << "l1= " << l1 << '\n';
}

Возможный вывод:

l1= -9223372036854775808
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...