Форум программистов, компьютерный форум CyberForum.ru

double - C++

Восстановить пароль Регистрация
 
 
Ksan
26 / 26 / 0
Регистрация: 02.11.2010
Сообщений: 370
04.07.2012, 17:37     double #1
Если преобразовать double к char*, то какие байты будут отвечать за целую часть, а какие за дробную?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Catstail
Модератор
 Аватар для Catstail
21486 / 10239 / 1668
Регистрация: 12.02.2012
Сообщений: 17,118
04.07.2012, 17:56     double #2
Не так просто... Числа типа double хранятся в виде двух битовых полей мантиссы (нормализованная дробная часть) и двоичного порядка.
cppGhost
32 / 30 / 1
Регистрация: 21.06.2012
Сообщений: 91
04.07.2012, 17:57     double #3
Не совсем понял, но привести число к указателю на char? Так компилятор не даст скорее всего.
C++
1
2
3
4
5
double var = 30;
char *p = "O";
 
p = var;    // тут ругнется при компиляции
*p = var;  // тут выдаст предупреждение и потом может вообще упасть
Ksan
26 / 26 / 0
Регистрация: 02.11.2010
Сообщений: 370
04.07.2012, 17:58  [ТС]     double #4
cppGhost,
C++
1
2
3
double val; 
char* p; 
p = (char*)&val;
Catstail
Модератор
 Аватар для Catstail
21486 / 10239 / 1668
Регистрация: 12.02.2012
Сообщений: 17,118
04.07.2012, 17:58     double #5
Компилятор даст, если сделать правильно...

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include "stdio.h"
 
int main(int argc, char* argv[])
{
    double x=111.111;
    char *c;
 
    c= (char *) &x;
 
    printf("%d\n",c[0]);
    printf("%d\n",c[1]);
    printf("%d\n",c[2]);
    printf("%d\n",c[3]);
    printf("%d\n",c[4]);
    printf("%d\n",c[5]);
    printf("%d\n",c[6]);
    printf("%d\n",c[7]);
 
    return 0;
}
Ksan
26 / 26 / 0
Регистрация: 02.11.2010
Сообщений: 370
04.07.2012, 18:00  [ТС]     double #6
Catstail, понятно. Значит в это лучше не лезть?
Catstail
Модератор
 Аватар для Catstail
21486 / 10239 / 1668
Регистрация: 12.02.2012
Сообщений: 17,118
04.07.2012, 18:06     double #7
Вовсе нет! Это по-своему интересно! Понимая, как хранятся числа с плав. точкой, ты всегда сможешь (если захочешь) построить программную плавающую арифметику на любой платформе. Или построить свою арифметику сверхвысокой точности. Лишних знаний не бывает!
cppGhost
32 / 30 / 1
Регистрация: 21.06.2012
Сообщений: 91
04.07.2012, 18:07     double #8
Хорошо, так компилятор даст
C++
1
p = (char*)&val;
но что мы тут делаем. адрес переменной типа double подставляем в указатель типа char. double 8 байт, char 1. кстати, проверил MSVS 2008, в p нет ожидаемого значения.
Ksan
26 / 26 / 0
Регистрация: 02.11.2010
Сообщений: 370
04.07.2012, 18:09  [ТС]     double #9
cppGhost, это даст побайтовое представление переменной. попробуй с int
cppGhost
32 / 30 / 1
Регистрация: 21.06.2012
Сообщений: 91
04.07.2012, 18:22     double #10
хм, а как с int будет представляться число 257, скажем, если char* 1 байт?
не, может я просто знаю условие задачи, ради которой это все тут началось. с другой стороны для себя кое-что новое узнал, спасибо )

Добавлено через 1 минуту
Кстати, с float тоже не работает, хотя как и int те же 4 байта

Добавлено через 2 минуты
Да и вообще не понятно. Вот есть char *p, он знает, что значение лежит по адресу: p + sizeof(char). Мы даем ему адрес переменной типа int, как он определит, что нужно брать уже sizeof(int)?
Catstail
Модератор
 Аватар для Catstail
21486 / 10239 / 1668
Регистрация: 12.02.2012
Сообщений: 17,118
04.07.2012, 18:30     double #11
Смотри. Берем код:

C++
1
2
3
4
5
6
7
8
9
10
11
#include "stdio.h"
 
int main(int argc, char* argv[])
{
    int x=234;
    unsigned char *c;
    c= (unsigned char *) &x;
    printf("%2x\n",c[0]);
    printf("%2x\n",c[1]);
    return 0;
}
Запускаем. И видим вывод:

ea
0

Разберемся. Для начала переведем 234 в 16-ричную систему. Получаем 23410=00EA16. Теперь нужно вспомнить, что в интеловских процессорах принят обратный порядок байтов. Поэтому у нас и получилось EA00, что для человека означает 00EA.

А если подставить x=-234. То вывод будет:

16
FF

Что сие значит? Отрицательные числа хранятся в дополнительном коде. Он получается так: сначала берем исходное число и заменяем нули единицами, единицы - нулями (инверсия битов). Из 00EA получится FF15. А потом добавляем единицу к младшему разряду.
Получаем FF16. В памяти байты переставляются, вот и получается 16FF. Все понятно?
cppGhost
32 / 30 / 1
Регистрация: 21.06.2012
Сообщений: 91
04.07.2012, 18:37     double #12
C++
1
printf("%2x\n",c[1]);
а вот это что такое? я ведь могу написать и
C++
1
printf("%2x\n",c[2]);
и будет тоже 0. я просто к тому, что если число, лежащее в int Больше 255, то никакой c[0]...c[1]...c[2] не отобразит исходное число. или я не прав?
Catstail
Модератор
 Аватар для Catstail
21486 / 10239 / 1668
Регистрация: 12.02.2012
Сообщений: 17,118
04.07.2012, 18:46     double #13
В моей системе тип int имеет длину 4 байта. Поэтому c[0],c[1],c[2],c[3] будут частями нашего int. А вот с[4] уже к числу не относится.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include "stdio.h"
 
int main(int argc, char* argv[])
{
   int x=-234;
   unsigned char *c;
   printf("Size of int=%d\n",sizeof(int));
   с= (unsigned char *) &x;
   printf("%2x\n",c[0]);
   printf("%2x\n",c[1]);
   printf("%2x\n",c[2]);
   printf("%2x\n",c[3]);
 
   printf("%2x\n",c[4]); // напечаться может что угодно...
 
   return 0;
}
Миниатюры
double  
Schizorb
 Аватар для Schizorb
508 / 460 / 16
Регистрация: 07.04.2012
Сообщений: 865
Записей в блоге: 1
Завершенные тесты: 1
04.07.2012, 18:50     double #14
Цитата Сообщение от cppGhost Посмотреть сообщение
я просто к тому, что если число, лежащее в int Больше 255, то никакой c[0]...c[1]...c[2] не отобразит исходное число.
Отобразит... Значение же не будет копироваться в переменную типа char. Указатель и индексация тут используются просто для доступа к отдельным байтам исходного значения.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <cstdio>
 
int main(int argc, char* argv[])
{
    int x = 30000;
    unsigned char *c;
    c = (unsigned char *) &x;
    
    for(int i = 0; i < sizeof(int); ++i)
    {
        printf("%2x\n",c[i]);
    }
    
    return 0;
}
cppGhost
32 / 30 / 1
Регистрация: 21.06.2012
Сообщений: 91
04.07.2012, 18:51     double #15
вот у вас
Цитата Сообщение от Catstail Посмотреть сообщение
int x=-234;
число отрицательное, это специально? просто если заменить на

Цитата Сообщение от Catstail Посмотреть сообщение
int x=400;
, то мы не получим в выводе побайтовые значения
Catstail
Модератор
 Аватар для Catstail
21486 / 10239 / 1668
Регистрация: 12.02.2012
Сообщений: 17,118
04.07.2012, 18:53     double #16
Получим! 90 01 00 00, что означает 0000019016=40010
Да хоть 40000 подставь (получишь 40 9с 00 00), что равно 00009с4016. В десятичную переведи сам.
cppGhost
32 / 30 / 1
Регистрация: 21.06.2012
Сообщений: 91
04.07.2012, 18:57     double #17
ок, тогда такой вопрос: вот мы проинициализировали так
C++
1
char *p = 'a';
где-то в памяти, в ячейке нашлось место для этого несчастного байта =)) потом сделали так
C++
1
2
int x = 400;
p = (unsigned char *) &x;
где гарантия, что в памяти после ячейки p есть свободное место, чтобы туда положить еще три байта? я теперь не говорю, что нельзя, но хочу понять валидность такого преобразования
Catstail
Модератор
 Аватар для Catstail
21486 / 10239 / 1668
Регистрация: 12.02.2012
Сообщений: 17,118
04.07.2012, 19:05     double #18
У тебя имеется элемент непонимания... Код
C++
1
char *p = 'a';
Выделяет байт, заносит в него 'a', и устанавливает указатель p на адрес этого байта.

а следующий за ним код

C++
1
2
int x = 400;
p = (unsigned char *) &x;
выделяет 4 байта под Х, заносит туда 400 и переустанавливает указатель p на адрес Х. Начиная с этого момента указатель забыл, что он раньше указывал на байт 'a'.
cppGhost
32 / 30 / 1
Регистрация: 21.06.2012
Сообщений: 91
04.07.2012, 19:07     double #19
заносит туда 400 и переустанавливает указатель p на адрес Х
тут да, это я упустил

Цитата Сообщение от Catstail Посмотреть сообщение
Начиная с этого момента указатель забыл, что он раньше указывал на байт 'a'.
а как он может забыть, если он имеет тип char. неужели после приведения в стиле C указатель запоминает, на что он действительно стал указывать?

хотя да. это же мы знаем. сам то он не в курсе. что же, спасибо за разъяснение.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
04.07.2012, 19:13     double
Еще ссылки по теме:

Почему перестает работать программа при замене double на long double? C++
Преобразовать 2 числа int в 1 число float(double) | double int1.int2 C++
Почему мы пишем double x (double y)? а не через запятую double x,y C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Catstail
Модератор
 Аватар для Catstail
21486 / 10239 / 1668
Регистрация: 12.02.2012
Сообщений: 17,118
04.07.2012, 19:13     double #20
Тип указателя char означает только то, что при разыменовании (добавл. *) будет браться один байт.
Yandex
Объявления
04.07.2012, 19:13     double
Ответ Создать тему
Опции темы

Текущее время: 18:48. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru