приведение от двойного * к int теряет точность - PullRequest
2 голосов
/ 07 июня 2019

d - это данные типа double, а p - указатель на них. Когда оба они явно приводятся к int явно, это дает следующую ошибку для приведения указателя p. : приведение от double* к int теряет точность

#include<iostream>
using namespace std;
int main()
{
    int i,j;
    double d=3.5;
    double* p=&d;
    i=(int)d;
    j=(int)p;   // this line gives the error
    cout<<i<<" "<<j;
    return 0;
}

Я ожидал, что ошибка будет "неверное преобразование из double* в int. Почему это не так?

Кроме того, почему приведение к данным d не выдает ошибку «теряет точность», если это происходит для указателя p?

Ответы [ 4 ]

1 голос
/ 07 июня 2019

Вы разыгрываете от poiner p до int. Это сужение соглашения. У вас будет часть адреса памяти. Что еще вы ожидаете?

1 голос
/ 07 июня 2019

Я ожидал, что ошибка будет "неверное преобразование из 'double *' в 'int'".Почему это не так?

Я предполагаю, что это просто зависимый от компилятора способ справиться с этой ошибкой.В clang я получаю нечто подобное, может быть, более информативное:

error: cast from pointer to smaller type 'int' loses information

Кроме того, почему приведение к данным d не дает ошибку «теряет точность», если это происходит для указателя p?

Преобразование из числа с плавающей запятой или двойного в целое число входит в число стандартных преобразований, не является ошибочным и иногда полезным.Это не должно приводить к ошибке, подробнее об этом здесь ,

Значение типа с плавающей запятой может быть преобразовано в значение любого целочисленного типа.Дробная часть усекается, то есть дробная часть отбрасывается.Если значение не может вписаться в тип назначения, поведение не определено (даже если тип назначения не имеет знака, арифметика по модулю не применяется).Если тип назначения - bool, это логическое преобразование (см. Ниже).

Значение типа перечисления с целым числом или с незаданной областью может быть преобразовано в значение типа с плавающей запятой.Если значение не может быть представлено правильно, то реализация определяется, будет ли выбрано самое близкое более высокое или самое близкое нижнее представимое значение, хотя, если поддерживается арифметика IEEE, округление по умолчанию до ближайшего.Если значение не может вписаться в тип назначения, поведение не определено.Если тип источника - bool, значение false преобразуется в ноль, а значение true преобразуется в единицу.

0 голосов
/ 07 июня 2019

int не гарантирует возможность удерживать значение указателя.В вашем случае я считаю, intptr_t будет работать.

0 голосов
/ 07 июня 2019

Вы теряете точность, это довольно очевидно.

В этом случае есть две причины, по которым вы делаете.

  1. Целое число имеет только 4 байта, тогда как двойное имеет 8, что означает, что вы не можете поместить весь двойной в целое число. (На самом деле это реализация определена)
  2. У двойного числа есть десятичные числа, у целого - нет, поэтому целое число просто не может содержать информацию о десятичных числах.

Причина, по которой ошибки строки заключаются в том, что вы пытаетесь привести указатель к целому числу, что невозможно, то, что вы хотели сделать, это j = (int)*p;

В вашем коде есть несколько плохих практик.

  1. с использованием пространства имен std; Почему "использование пространства имен std;" считается плохой практикой?

https://isocpp.org/wiki/faq/coding-standards#using-namespace-std

Как использовать итератор? (пример возникновения проблем)

Путаница с указателями и ссылками в C ++ (еще один пример того, что это вызывает проблемы; использование std :: swap; также вызывает ту же самую проблему)

  1. броски в стиле C Это (type), в вашем случае конкретно (int) Есть два основных приведения, которые должны использоваться в C ++: static_cast и reinterpret_cast. (Есть еще 2 типа, const_cast и dynamic_cast, но они не имеют значения в этом случае, и const_cast почти никогда не должен использоваться)

Оба принимают параметр шаблона к результирующему типу.

В этом случае вы, вероятно, могли бы i = static_cast<int>(d);

Для второго приведения, j =, вы должны (на самом деле вы не должны разыгрывать указатели на разные типы)

j = *reinterpret_cast<int*>(p);

Конечно, приведение двойных чисел к целым не считается хорошим, но это должно исправить ошибку вашего компилятора.

...