Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 21.06.2017, 13:51   #51
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Вот подробнее про qmake

https://stackoverflow.com/questions/...ile-with-qmake

А вот про aliasing, похоже на С++ ток через memcpy само переносимо, и надеяться на оптимизацию:
http://dbp-consulting.com/tutorials/StrictAliasing.html
alexzk вне форума Ответить с цитированием
Старый 21.06.2017, 13:55   #52
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Т.е. вот такой вариант:
Код:
template<class T, class Src>
typename std::enable_if<std::is_pointer<T>::value, T>::type union_cast(Src src)
{
//    union
//    {
//        Src s;
//        T d;
//    } tmp;
//    tmp.s = src;
//    return tmp.d;
    T tmp;
    memcpy(&tmp, &src, sizeof (tmp));
    return tmp;
}

Последний раз редактировалось alexzk; 21.06.2017 в 14:21.
alexzk вне форума Ответить с цитированием
Старый 21.06.2017, 15:56   #53
Croessmah
Вредный кошак
Участник клуба
 
Аватар для Croessmah
 
Регистрация: 14.10.2012
Сообщений: 1,159
По умолчанию

Не понял зачем там enable_if.

Ну и размер лучше проверить:
Код:
static_assert(sizeof(T) <= sizeof(Src), "result type is small");
Croessmah вне форума Ответить с цитированием
Старый 21.06.2017, 17:01   #54
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Цитата:
Сообщение от Croessmah Посмотреть сообщение
Не понял зачем там enable_if.

Ну и размер лучше проверить:
Код:
static_assert(sizeof(T) <= sizeof(Src), "result type is small");

чтоб только указатели преобразовывались. Для остального оно нафик не над. Кому вдруг нада - можно убрать

Последний раз редактировалось alexzk; 21.06.2017 в 17:04.
alexzk вне форума Ответить с цитированием
Старый 21.06.2017, 18:47   #55
Croessmah
Вредный кошак
Участник клуба
 
Аватар для Croessmah
 
Регистрация: 14.10.2012
Сообщений: 1,159
По умолчанию

т.е. и T и Src - указатели?
Тогда это не спасет от нарушения strict-aliasing в коде, который будет использовать такой union_cast.
Код:
#include <iostream>
#include <cstring>
#include <cstddef>

template<class T, class Src>
typename std::enable_if<std::is_pointer<T>::value, T>::type union_cast(Src src)
{
    T tmp;
    memcpy(&tmp, &src, sizeof (tmp));
    return tmp;
}



void foo(double *d, uint64_t *p)
{
    *d = 10;
    *p = 30;
    std::cout << *d << std::endl;
    std::cout << *p << std::endl;
    std::cout << "value d:" << d << std::endl;
    std::cout << "value p:" << p << std::endl;
}


int main()
{
    double x = 10.0;
    uint64_t *p = union_cast<uint64_t*>(&x);
    foo(&x, p);
    std::cout << x << std::endl;
    std::cout << *p << std::endl;
}
http://rextester.com/LGKH3036

Как видим, адрес в p совпадает с адресом переменной x, только вот вывод интересный. )))
Croessmah вне форума Ответить с цитированием
Старый 21.06.2017, 20:36   #56
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Цитата:
Сообщение от Croessmah Посмотреть сообщение
т.е. и T и Src - указатели?
Тогда это не спасет от нарушения strict-aliasing в коде, который будет использовать такой union_cast.
Код:
#include <iostream>
#include <cstring>
#include <cstddef>

template<class T, class Src>
typename std::enable_if<std::is_pointer<T>::value, T>::type union_cast(Src src)
{
    T tmp;
    memcpy(&tmp, &src, sizeof (tmp));
    return tmp;
}



void foo(double *d, uint64_t *p)
{
    *d = 10;
    *p = 30;
    std::cout << *d << std::endl;
    std::cout << *p << std::endl;
    std::cout << "value d:" << d << std::endl;
    std::cout << "value p:" << p << std::endl;
}


int main()
{
    double x = 10.0;
    uint64_t *p = union_cast<uint64_t*>(&x);
    foo(&x, p);
    std::cout << x << std::endl;
    std::cout << *p << std::endl;
}
http://rextester.com/LGKH3036

Как видим, адрес в p совпадает с адресом переменной x, только вот вывод интересный. )))
Да ну, пример дурацкий. Флоат же хранится не так, как инты...вот взять 32 бита, поделить на 16 и обменять ...например (и кстати, strict-aliasing это вообще ТОЛЬКО про указатели, и ссылки, которые суть указатель - сахар синтаксический).

Вот, даже явно задал -fstrict-aliasing и он не возникает даже там, где нужен ...

Код:
//g++  5.4.0

#include <iostream>
#include <cstring>
#include <cstddef>

template<class T, class Src>
typename std::enable_if<std::is_pointer<T>::value, T>::type union_cast1(Src src)
{
        union
    {
        Src s;
        T d;
    } tmp;
    tmp.s = src;
    return tmp.d;
}

template<class T, class Src>
typename std::enable_if<std::is_pointer<T>::value, T>::type union_cast2(Src src)
{
//    union
//    {
//        Src s;
//        T d;
//    } tmp;
//    tmp.s = src;
//    return tmp.d;
    static_assert(sizeof(T) <= sizeof(Src), "result type is small");
    T tmp;
    memcpy(&tmp, &src, sizeof (tmp));
    return tmp;
}

uint32_t
swaphalves(uint32_t a)
{
    uint32_t acopy=a;
    uint16_t *ptr=(uint16_t*)&acopy;// can't use static_cast<>, not legal.
        // you should be warned by that.
    std::swap(ptr[0], ptr[1]);    
    return acopy;
}

uint32_t uswap1(uint32_t a)
{
    uint32_t acopy=a;
    uint16_t *ptr=union_cast1<uint16_t*>(&acopy);// can't use static_cast<>, not legal.
        // you should be warned by that.
    std::swap(ptr[0], ptr[1]);    
    return acopy;
}

uint32_t uswap2(uint32_t a)
{
    uint32_t acopy=a;
    uint16_t *ptr=union_cast1<uint16_t*>(&acopy);// can't use static_cast<>, not legal.
        // you should be warned by that.
    std::swap(ptr[0], ptr[1]);    
    return acopy;
}

int main()
{
    uint32_t value = 0xaaaaeeee;
    printf("%08X\n", value);
    printf("%08X\n", swaphalves(value));
    printf("%08X\n", uswap1(value));
    printf("%08X\n", uswap2(value));
        
}
Цитата:
AAAAEEEE
EEEEAAAA
EEEEAAAA
EEEEAAAA

Последний раз редактировалось alexzk; 21.06.2017 в 20:39.
alexzk вне форума Ответить с цитированием
Старый 21.06.2017, 20:44   #57
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

...а в вашем примере тоже все верно, вывод из мейн

1.4822e-322
30

это и есть корректно - в 1 память записалось, а вот в foo, как-то соптимизировалось (т.е. он 1 константу по указателю положил, и сразу же ее на экран отправил, а в памяти таки изменилось, что видно в мейн дальше), т.к. вы не выполняете над переменными действий.

Вот если форсировать компилер, и сказать, что значения меняются внутир фуу:
Код:
*d = 10;
    *p = 30;    
    
    
    *p += 1;
    *d = *p + 1;
Тогда:
32
4629700416936869888
value d:0x7ffe41f99030
value p:0x7ffe41f99030
32
4629700416936869888

Последний раз редактировалось alexzk; 21.06.2017 в 20:50.
alexzk вне форума Ответить с цитированием
Старый 21.06.2017, 22:03   #58
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

..кароче да, шото я фигню понаписал - удалил из проекта тот юнион_каст совсем, у меня он не нужен был, а чужим сырцам запретил алиасинг. После перепрочтения кода, оказалось, я это придумал из-за тяжкого наследия С, типа указатели в либу приводить unsigned char <---> char. Вернул reinterpret_cast, т.к. это можно.

Последний раз редактировалось alexzk; 21.06.2017 в 22:16.
alexzk вне форума Ответить с цитированием
Старый 22.06.2017, 00:38   #59
Croessmah
Вредный кошак
Участник клуба
 
Аватар для Croessmah
 
Регистрация: 14.10.2012
Сообщений: 1,159
По умолчанию

Цитата:
Сообщение от alexzk Посмотреть сообщение
а вот в foo, как-то соптимизировалось
Код:
void foo(double *d, uint64_t *p)
{
    *d = 10;
    *p = 30;//p указывает на данные другого типа, значит он не может изменить *d
    std::cout << *d << std::endl;//*d нигде не менялся до этого, значит не нужно лезть в память для его загрузки. Да и вообще можно тупо прописать 10. )))
    //...
}
Добавим -fno-strict-aliasing и уже не прокатит такая оптимизация.
Код:
*p = 30;//p указывает на данные другого типа но есть шанс того, что это поменяет *d, значит придется теперь ВСЕГДА загружать *d заново
Croessmah вне форума Ответить с цитированием
Старый 22.06.2017, 06:55   #60
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Цитата:
Сообщение от Croessmah Посмотреть сообщение
Код:
void foo(double *d, uint64_t *p)
{
    *d = 10;
    *p = 30;//p указывает на данные другого типа, значит он не может изменить *d
    std::cout << *d << std::endl;//*d нигде не менялся до этого, значит не нужно лезть в память для его загрузки. Да и вообще можно тупо прописать 10. )))
    //...
}
Добавим -fno-strict-aliasing и уже не прокатит такая оптимизация.
Код:
*p = 30;//p указывает на данные другого типа но есть шанс того, что это поменяет *d, значит придется теперь ВСЕГДА загружать *d заново
Вобщем умные слова и статьи меня ток путают ) - получается, именно вот это "Да и вообще можно тупо прописать 10. )" и есть результат стрикт-алиасинг? Ну и нафиг его. Пользуйтесь std::vector. У меня вон на 200 файлов, в 1 месте ток есть арифметика указателей - проверяю, utf-8 или wchar_t (16) строка, путем проверки нулей. А так, даже массивы std::array (и в ардуино такой подход работает, не хуже С). На кой черт усложнять жизнь. Для счастья хватает косяков, что на линуксе std::thread имеет стек 2мб, а на маке 512кб, соотв. на маке не объяснимые краши де попало из-за отказа выделения памяти. Пришлось boost::thread в итоге.

Последний раз редактировалось alexzk; 22.06.2017 в 07:15.
alexzk вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
MMX сложить два числа gansm Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 13 29.10.2010 05:16
как сложить два числа с плавающей точкой forsy Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 19 29.03.2010 02:15
Макрос: сложить два числа белочка Microsoft Office Excel 6 23.12.2009 22:02
Сложить два числа и вывести результат на экран We1c0m3 Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 2 23.05.2009 11:41
Сложить два числа iwaniwan Win Api 3 23.04.2009 06:27