Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.80/35: Рейтинг темы: голосов - 35, средняя оценка - 4.80
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
1

Не получается reinterpret_cast<uint64_t>

31.12.2014, 10:50. Показов 6842. Ответов 88
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
C++
1
2
3
4
5
 double x;
 uint64_t u;
 TDoubleMantissFormatMarker f;
 x=1.23456e+2;
 u=reinterpret_cast<uint64_t>(x);
на 5-ю строку пишет:
C:\Projects\Test\Test\test.cpp|68|error: invalid cast from type 'double' to type 'uint64_t {aka long long unsigned int}'|
.
1
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
31.12.2014, 10:50
Ответы с готовыми решениями:

А где uint64_t декларирован?
А где uint64_t декларирован?

Uint64_t - проверить его существование
Вопрос в следующем. Стандарт С99 не обязывает реализовывать типы с точным размером (напр. int8_t...

Ошибка компиляции: 'uint64_t' does not name a type
при компиляции проекта возникает следующая ошибка: ...\library\system.h:164: ошибка: 'uint64_t'...

Модуль часов DS3231, преобразование UNIX TimeStamp uint32_t в uint64_t
Доброго времени суток! Имеется модуль часов DS3231, пользуюсь либой отсюда ...

88
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
31.12.2014, 19:32 21
Лучший ответ Сообщение было отмечено taras atavin как решение

Решение

Author24 — интернет-сервис помощи студентам
Цитата Сообщение от hoggy Посмотреть сообщение
ример ситуации, иллюстрирующей, как используя reinterpret_cast можно налететь на неровные адреса.
Справедливости ради, в задаче ТС такое скорее всего действительно невозможно.
Но я говорил в общем. А пример вот такой:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void test()
{
    unsigned char buf[] = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8};
 
    // например, адреса должны быть выровнены по границе 4 байт.
 
    uint8_t  a = *reinterpret_cast<uint8_t*>(&buf[0]);
    uint32_t b = *reinterpret_cast<uint32_t*>(&buf[1]); // unaligned access, попытка чтения 32битного целого по адресу не кратному 4 байтам
 
    printf("%x\n", &buf[0]);
    printf("%x\n", &buf[1]);
 
    printf("%d\n", int(&buf[0]) % sizeof(uint32_t));
    printf("%d\n", int(&buf[1]) % sizeof(uint32_t));
}
1
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
31.12.2014, 19:47 22
Цитата Сообщение от DrOffset Посмотреть сообщение
А пример вот такой:
Понял вас.

Технически такое может быть, например при десереализации из блоба, в который закатали упакованные структуры...
0
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
31.12.2014, 19:51 23
Цитата Сообщение от hoggy Посмотреть сообщение
Технически такое может быть, например при десереализации из блоба, в который закатали упакованные структуры...
Да-да.
Может быть конечно зря я панику тут навожу. Но по работе часто приходится иметь дело с такими архитектурами, где это критично (в частности 32-разрядные MIPS и SPARC). Поэтому у меня выработалась уже некоторая паранойя на этот счет
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
01.01.2015, 07:11  [ТС] 24
Цитата Сообщение от DrOffset Посмотреть сообщение
enum { bytes_count = sizeof(uint64_t) };
Что делает этот член?

Добавлено через 36 секунд
Цитата Сообщение от DrOffset Посмотреть сообщение
template <typename ArgT> raw_8bytes(ArgT arg, typename std::enable_if<sizeof(ArgT) == bytes_count>::type * = nullptr) { std::memcpy(&value, &arg, bytes_count); }
И что здесь изменилось то?

Добавлено через 34 секунды
Цитата Сообщение от DrOffset Посмотреть сообщение
operator uint64_t() const
А зачем здесь это?

Добавлено через 10 минут
Цитата Сообщение от DrOffset Посмотреть сообщение
Ну вдруг тебе потом захочется сделать 2 сырых байта, 4 сырых байта или вообще 32 сырых байта.
Конечно захочу. Но:
1. Поняв принцип, не проблема сделать это вручную.
2. От размера должен зависеть алгоритм.

Добавлено через 16 минут
Цитата Сообщение от DrOffset Посмотреть сообщение
Да-да.
Может быть конечно зря я панику тут навожу. Но по работе часто приходится иметь дело с такими архитектурами, где это критично (в частности 32-разрядные MIPS и SPARC). Поэтому у меня выработалась уже некоторая паранойя на этот счет
А мне вот интересно, почему в таких случаях не выровненное чтение не компилится в побайтное. Даже если процессор не может читать произвольный байт регистра, что ожидаемо, можно ведь побайтно сравнять в выровненном участке оперативы, а потом загрузить все 8 байт.

Добавлено через 8 минут
Цитата Сообщение от DrOffset Посмотреть сообщение
uint32_t b = *reinterpret_cast<uint32_t*>(&buf[1]);
Приводить через указатель? Понятно.

Добавлено через 6 минут
Цитата Сообщение от DrOffset Посмотреть сообщение
::type * = nullptr
Что это значит?
0
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
01.01.2015, 15:27 25
Цитата Сообщение от taras atavin Посмотреть сообщение
Что делает этот член?
Чтобы не писать по нескольку раз sizeof(uint64_t). Зачем вообще делают именованные константы знаешь? Вот это тоже самое.

Цитата Сообщение от taras atavin Посмотреть сообщение
Что это значит?
Читай про SFINAE и enablle_if

Цитата Сообщение от taras atavin Посмотреть сообщение
Конечно захочу. Но:
1. Поняв принцип, не проблема сделать это вручную.
2. От размера должен зависеть алгоритм.
Насчет вручную - это уж как хочешь. Но зачем копипастить то, что хорошо шаблонизируется?
Насчет второго пункта - не вижу преград для этого.

Цитата Сообщение от taras atavin Посмотреть сообщение
А зачем здесь это?
Чтобы работать с этим типом так, как будто это PatternT. Базовая идея такая: мы создаем тип, внутреннее представление которого определяет PatternT (где PatternT = uint64_t, в других случаях может быть, например, uint32_t и т.д.). Этот тип свободно приводится к PatternT в выражениях посредством этого оператора (operator PatternT). А шаблонный конструктор позволяет на низком уровне записать во внутреннее представление какие угодно данные той же разрядности. Можно конечно убрать инкапсуляцию и просто все время писать вот так:
C++
1
2
3
4
5
6
7
void foo(uint64_t x);
//......
 
double a = 3.14;
uint64_t param;
memcpy(&param, &a, sizeof(param));
foo(param);
Но это некрасиво, разрядность не контролируется (а контролировать придется обычным if или тернарным оператором), и в целом ошибкоопасно.

Цитата Сообщение от taras atavin Посмотреть сообщение
А мне вот интересно, почему в таких случаях не выровненное чтение не компилится в побайтное.
Компилятор не знает ничего о конкретных адресах.
Вообще на некоторых архитектурах есть специальные команды для работы с невыровненными данными, но по-умолчанию в целях эффективности компилятор их не использует.

Добавлено через 2 минуты
Цитата Сообщение от taras atavin Посмотреть сообщение
И что здесь изменилось то?
Ничего. Чтобы понять эту строчку читай ссылки, который я выше дал.
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
01.01.2015, 15:38  [ТС] 26
Цитата Сообщение от DrOffset Посмотреть сообщение
Чтобы не писать по нескольку раз sizeof(uint64_t). Зачем вообще делают именованные константы знаешь? Вот это тоже самое.
1. А почему под энамом?
2. А что за проблема написать sizeof?
3. То есть много раз размещать восьмёрку в оперативе по-вашему нормально? Да ещё и в стеке.

Добавлено через 57 секунд
Цитата Сообщение от DrOffset Посмотреть сообщение
Ничего. Чтобы понять эту строчку читай ссылки, который я выше дал.
Какую "эту строчку"? Там ваще то тело функции.

Добавлено через 1 минуту
Цитата Сообщение от DrOffset Посмотреть сообщение
Чтобы работать с этим типом так, как будто это PatternT.
Зачем? В теле одной функции применить точечную нотацию - не проблема, а внутри тот же PatternT. При этом код будет оптимален и полностью совпадёт с кодом, юзающим инлайн-версию того же оператора приведения. Читает то одна единственная функция, по всему тексту надо только писать и после обработки наружу выдаётся PatternT.
0
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
01.01.2015, 15:47 27
Цитата Сообщение от taras atavin Посмотреть сообщение
1. А почему под энамом?
2. А что за проблема написать sizeof?
3. То есть много раз размещать восьмёрку в оперативе по-вашему нормально? Да ещё и в стеке.
Что? Ничего подобного. Ничего нигде не размещается - это константа времени компиляции.
Почему ссылки мои не смотришь? Я вообще там выше давал ссылку, где есть дизассемблер этого кода. Там хорошо видно, что никакого оверхеда этот код не дает вообще.

Цитата Сообщение от taras atavin Посмотреть сообщение
Какую "эту строчку"? Там ваще то тело функции.
Ну ты процитировал тело функции в одну строчку. Вот я и сказал "строчку".

Цитата Сообщение от taras atavin Посмотреть сообщение
Зачем? В теле одной функции применить точечную нотацию - не проблема, а внутри тот же PatternT. При этом код будет оптимален и полностью совпадёт с кодом, юзающим инлайн-версию того же оператора приведения.
Я свои решения не патентую. Если что-то хочешь изменить - меняй
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
01.01.2015, 15:50  [ТС] 28
Цитата Сообщение от DrOffset Посмотреть сообщение
Читай про SFINAE и enablle_if
Угловые скобки как раз уже понятны. А вот что такое
C++
1
::type * = nullptr
?
0
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
01.01.2015, 15:52 29
Цитата Сообщение от taras atavin Посмотреть сообщение
Угловые скобки как раз уже понятны. А вот что такое
Параметр по-умолчанию, без имени.
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
01.01.2015, 15:52  [ТС] 30
Цитата Сообщение от DrOffset Посмотреть сообщение
Что? Ничего подобного. Ничего нигде не размещается - это константа времени компиляции.
Ваще не понял.
0
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
01.01.2015, 15:56 31
Цитата Сообщение от taras atavin Посмотреть сообщение
Ваще не понял.
В чем проблема?
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
01.01.2015, 15:58  [ТС] 32
Кстати, проще уж написать сайзоф, чем несколько раз вспомнить, как его переобозвал, а константы применяются совсем не для этого. Константа применяется, когда некоторое число можно как-то осмысленно обозвать и оно может измениться в ходе разработки. А здесь другие значения существуют одновременно для других целей, а изменение в следующей версии исключено и при это единственное осмысленное имя - тот самый sizeof.
0
3257 / 2059 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
01.01.2015, 15:58 33
Цитата Сообщение от DrOffset Посмотреть сообщение
Параметр по-умолчанию, без имени.
Я мимо проходил и не особо вникал: не логичнее этот параметр сделать параметром шаблона, а не функции? Он же функционально только ради идиомы sfinae, а не для приема конкретного аргумента?
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
01.01.2015, 16:05  [ТС] 34
Когда речь заходит о SFINAE, это обязательно связано с перегрузкой функций.
Это работает при автоматическом выводе типов шаблона (type deduction) по аргументам функции.
Некоторые перегрузки могут отбрасываться в том случае, когда их невозможно инстанциировать из-за возникающей синтаксической ошибки; компиляция при этом продолжается как ни в чём не бывало, без ошибок.
Отбросить могут только шаблон.
SFINAE рассматривает только заголовок функции, ошибки в теле функции не будут пропущены.
То есть мне на каждый приводимый к raw_8bytes типу что то прописать в исходнике? Не пойдёт.
0
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
01.01.2015, 16:12 35
Цитата Сообщение от 0x10 Посмотреть сообщение
Я мимо проходил и не особо вникал: не логичнее этот параметр сделать параметром шаблона, а не функции? Он же функционально только ради идиомы sfinae, а не для приема конкретного аргумента?
Он как раз для приема аргумента. Аргументы могут быть разные ведь. В первоначальном варианте в качестве аргумента может и массив нужного размера. Как этот размер проверить, если вынести проверку в параметр шаблона?

Цитата Сообщение от taras atavin Посмотреть сообщение
Кстати, проще уж написать сайзоф
Как вам будет угодно. В первоначальном варианте этого все равно не было. А позже добавилось для иллюстрации.

Цитата Сообщение от taras atavin Посмотреть сообщение
Константа применяется, когда некоторое число можно как-то осмысленно обозвать и оно может измениться в ходе разработки.
Меняем параметр шаблона, и число тоже меняется. Так что все верно и не противоречит тому, что ты написал. Но я повторюсь, не нравится - не используй. Не вижу смысла выносить это на обсуждение. Я тебе дал пример, он на самом деле крайне простой. Если ты почерпнешь оттуда что-то - хорошо, нет - еще лучше. Мое дело, как говорится, предложить, а твое дело отказаться.

Добавлено через 47 секунд
Цитата Сообщение от taras atavin Посмотреть сообщение
То есть мне на каждый приводимый к raw_8bytes типу что то прописать в исходнике? Не пойдёт.
Ничего не надо прописывать. Там же шаблон.
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
01.01.2015, 16:22 36
Цитата Сообщение от 0x10 Посмотреть сообщение
Я мимо проходил и не особо вникал: не логичнее этот параметр сделать параметром шаблона, а не функции? Он же функционально только ради идиомы sfinae, а не для приема конкретного аргумента?
Не логичнее.
Он нужен именно для приема конкретного аргумента.
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
01.01.2015, 16:22  [ТС] 37
Всё затеяно ради того, чтоб иметь одну версию и не перегружать.
Цитата Сообщение от DrOffset Посмотреть сообщение
Меняем параметр шаблона, и число тоже меняется. Так что все верно и не противоречит тому, что ты написал.
Вот только надо при каждом обращении вспоминать, как его обозвал. Зачем?
0
18840 / 9839 / 2408
Регистрация: 30.01.2014
Сообщений: 17,280
01.01.2015, 16:27 38
Цитата Сообщение от taras atavin Посмотреть сообщение
Вот только надо при каждом обращении вспоминать, как его обозвал. Зачем?
Что? Она для внутреннего использования. Не надо ничего вспоминать
При обращении пользователь класса даже не знает что она там есть

Добавлено через 2 минуты
Цитата Сообщение от taras atavin Посмотреть сообщение
Всё затеяно ради того, чтоб иметь одну версию и не перегружать.
Именно одну версию ты и будешь иметь.
Тип один, функция одна, а параметры любые заданной разрядности. Именно то, что ты хотел.
Не понимаю в чем проблема
0
4226 / 1795 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
01.01.2015, 16:36  [ТС] 39
Цитата Сообщение от DrOffset Посмотреть сообщение
Именно одну версию ты и будешь иметь.
Тип один, функция одна, а параметры любые заданной разрядности. Именно то, что ты хотел.
Не понимаю в чем проблема
Сколько версий конструктора будет в исполняемом коде? И типов как раз надо много. double, int64_t, uint64_t, классы... Всё надо свалить в одну функцию.
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
01.01.2015, 16:52 40
Цитата Сообщение от taras atavin Посмотреть сообщение
Сколько версий конструктора будет в исполняемом коде? И типов как раз надо много. double, int64_t, uint64_t, классы... Всё надо свалить в одну функцию.
Это глупость:

1. Экономия на спичках.
2. Компилятор сам оптимизирует во всех случаях, когда это возможно.
3. Если компилятор не оптимизировал, значит в любом случае придется запиливать перегрузки функци.
Вопрос только: это будет делать человек в ручную, или компилятор по шаблону?

DrOffset , можете глянуть ассм-код: оптимизировал ли компилятор конструкторы?

http://rextester.com/VOE80385

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <iostream>
#include <cstring>
 
template<class T>
struct RawBytes
{
    enum { SIZE = sizeof(T) };
    
    template<class U> RawBytes( U&& arg)
    { 
        static_assert( sizeof(U) == SIZE, 
            "ERROR: TYPE OF ARGUMENT HAS THE WRONG SIZE");
        
        Init(&arg, sizeof(U));
    }
    
    operator T()const { return mValue;}
    
private:
    
    void Init(const void* src, const size_t size)
    { 
        std::memcpy(&mValue, src, size );
    }
    
    
    T mValue;
};
 
typedef RawBytes<uint64_t>
    Raw8Bytes;
 
 
 
int main()
{
    std::cout << "Hello, world!\n";
    
    //расскоментируйте, что бы увидеть защиту от ошибок размеров типов в действии
    //{ char data=0; Raw8Bytes example(data); }
    
    int64_t  data2 = 1000; 
    uint64_t data1 = 1000; 
    
    Raw8Bytes example1(data1);
    Raw8Bytes example2(data2);
    
    uint64_t value1 = example1; 
    uint64_t value2 = example2; 
 
    std::cout<<"value1 = " << value1 <<std::endl;
    std::cout<<"value2 = " << value2 <<std::endl;
    
}
1
01.01.2015, 16:52
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
01.01.2015, 16:52
Помогаю со студенческими работами здесь

Reinterpret_cast
Не могу понять к чему тут этот каст и каким образом он влияет на результат. char zxc =...

reinterpret_cast
Подскажите плиз, чем отличается функция reinterpret_cast от static_cast? небольшой пример: const...

Reinterpret_cast
Результат работы функции reinterpret_cast равен нулю. Почему и как исправить? (Кстати ещё буду рад,...

reinterpret_cast<...>(...)
Всем привет! Сразу к делу. ВОПРОС: Как преобразовать переменную типа float в указатель типа...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru