2015-07-31 2 views
-1

я хочу, чтобы указатель типа двойной, чтобы указать на указатель типа Int, который указывает на другой вар:преобразование из базового типа в других указателей

int x=23; 
int *f_var =&x;  
double*l_ptr = (double *)f_var; 

оба этих указателей имеют один и тот же адрес, но когда я показываю их значения, f_var показывает хороший, но l_ptr показывает странное значение. Почему это происходит, и я буду рад, если вы объясните мне. Почему они не имеют того же значения? Если оба они указывают на одно и то же место, а double может хранить int, почему они имеют разные значения?

+1

«Я хочу, чтобы указатель типа double указывал на указатель типа int, который указывает на другой var:« ... зачем? – Caninonos

+1

Что вы ожидаете? –

+0

Это очень плохая идея. Даже если он делает то, что вы намереваетесь в своей системе, вы можете получать разные результаты в зависимости от размера каждого типа (afaik). Вы должны указать, каковы ваши намерения; это похоже на проблему. – Carcigenicate

ответ

1

Ваш вопрос ошибочен, но я попытаюсь ответить на несколько его аспектов.

Во-первых, int не является базовым типом для double. Также не указатель на int базовый тип для указателя на double. Поэтому этот вопрос неверно.

Во-вторых, нет гарантии, что тип с плавающей точкой может хранить каждое значение int. На практике это зависит от представления с плавающей запятой (сколько бит используется для представления мантиссы). Часто оказывается, что float или double может представлять некоторые из значений, которые могут быть int, но не другие (для которых он хранит значение, которое является приблизительным). Это часть компромисса переменной с плавающей запятой, способной представлять нецелые значения в большем диапазоне, чем int.

В-третьих, ваше описание «отображает их значения» неоднозначно. Если вы делаете

std::cout << f_var << ' ' << l_ptr << '\n'; 

или (более явно, не полагаясь на неявном преобразовании к аннулированию указателей)

std::cout << (void *)f_var << ' ' << (void *)l_ptr << '\n'; 

значения указателей (т.е. адрес они держат) будет напечатан. На практике выходы значений обычно будут одинаковыми - это их тип, который отличается, а не их значение. Но значения этих указателей являются адресом в памяти переменной x, а не значением x.

С другой стороны, если вы делаете

std::cout << *f_var << ' ' << *l_ptr << '\n'; 

результатом является неопределенное поведение, так как в настоящее время l_ptr разыменовываются как будто это указывает на double, несмотря указывая на int. Результатом этого может быть что угодно (печать мусора, значения печати, которые вы не ожидаете, переформатирование жесткого диска, что-либо). На практике он, вероятно, пытается интерпретировать биты, которые составляют int (т. Е. Переменную x), как если бы они представляли значение с плавающей запятой. Поскольку биты в int имеют различное значение от битов в double (в представлениях с плавающей запятой есть мантисса и экспонента, поэтому double может представлять значения, такие как 0.5E15 или 0.5E-3), тот же набор бит представляет другое значение , Существует также морщина, которая, как правило, составляет double, состоит из большего количества бит, чем int. Таким образом, путем печати таким образом ваш код интерпретирует случайную память справа от x как данные.

+0

Фактически, когда я делаю std :: cout << f_var << '' << l_ptr << '\ n'; код компилируется, и я вижу, что оба они имеют один и тот же адрес. И ваши второй инструкции показывают мне тот же результат, что и первый.Мой вопрос был для вашего thrid заявления. Это я хочу знать, могу ли я это сделать и его implication.Thx –

+0

Да, ладно. У меня был небольшой мозговой пердит с этим. Я исправлю сообщение в ближайшее время. – Peter

+0

после поиска я обнаружил что-то «правило строгого сглаживания». Это как-то связано с этими указателями на другие типы? –

1

На самом деле, когда вы делаете что:

int x=23; 
int *f_var = &x;  
double *l_ptr = (double *)f_var; 

l_ptr не является «указатель типа двойной [который указывает] на указатель типа Int» (как вы сказали), но указатель на двойной, который хранит адрес int. Выражение разыменования - это неопределенное поведение.
[Edit: на самом деле, отлитый из int* в double* уже неопределенное поведение, так l_ptr может хранить что-то другое, чем адрес x] [Edit: К сожалению, нет, вы можете «безопасно» reinterpret_cast из любого указателя любой указатель/интеграл, достаточно большой, чтобы удерживать его значение]

Вывод указателя на двойное фактическое сохранение адреса указателя на int не лучше, чем , предполагая, что вы достигнете назначения этого адреса указателю на двойное без вызывая неопределенное поведение (и указатель типа double, на самом деле, вероятно, не указатель, но я предположил, что вы имели в виду «указатель на выполнение» uble ").

Что вы видите при выводе *l_ptr* is probably the bitwise representation of x and probably some garbage data (because a double may be longer in memory than an int`) интерпретируется как двойной. Тем не менее, это может быть 42 или «вы делаете странные вещи» (или сбой, или вообще ничего): это неопределенное поведение, компилятор может генерировать все, что он хочет, и по-прежнему удовлетворять стандарту C++.

1

int и double не сохраняются одинаково. Для начала они, скорее всего, разных размеров в памяти. Но что более важно, их биты используются по-разному.

Так просто: повторная реинтеграция памяти int в виде двойника - это вздор, и от него не следует ожидать того же значения.

Если вы должны были сделать что-то вроде:

int a = 23; 
double b = 23; 
bool isSameBits = (memcmp(&a, &b, sizeof(a)) == 0); 

Это BOOL следует указать, что они действительно не используют свои биты таким же образом.

И bool isSameSize = (sizeof(a) == sizeof(b)); будет указывать, если они разных размеров.

Если вы хотите узнать больше о базовых деталях, то вы, возможно, можете сделать Google для чего-то вроде «макета памяти двойника».

0

Тогда можно сделать указатель типа, указывающего на другой указатель другого типа, и когда вы разыщите их, чтобы удержать оба они того же значения? Я только хочу знать, потому что, как вы видели, я ном.

Смежные вопросы