Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.223.107.124] |
|
Сообщ.
#1
,
|
|
|
В версии 32 бита int - 4 байта, size_t тоже 4 байта, но при переходе к 64 битам, int остается 4 байта, а size_t становится 8 байт. Возникает много предупреждений при преобразовании типов. Чтобы int стало 8 байт, надо использовать тип __int64. Править текст программы 200 файлов не хотелось бы. Существует ли способ решения этой задачи?
|
Сообщ.
#2
,
|
|
|
using ind_t = size_t
Везде заменить size_t на ind_t (только случайно не заменить выше указанную строчку). Все проверить, потом сделать так: using ind_t = int Я везде использую ind_t (чтоб потом, если что, скорректировать) А int/int64 (и типы других размеров) только там, где точно нужен именно 4/8 байт (например в union). |
Сообщ.
#3
,
|
|
|
При работе с vector:
vector<...> V; V.size(); // возвращает в 64-битном варианте size_t 8 байт. Вот с этим то и возникают проблемы. И есть другие функции, возвращающие 8-ми байтовый результат в 64-битной версии. |
Сообщ.
#4
,
|
|
|
Все меняйте на size_t
Другие типы используйте только там, где есть зависимость для длины типа. А вот при использовании OpenMP, в циклах тип должен быть знаковым..., вот у меня так: #ifdef _WIN64 using omp_t = __int64; #else using omp_t = int; #endif using ind_t = size_t; Добавлено А с учетом использования AVX, еще вот такое удобство сделал: #define _REAL_TYPE_ #ifdef _REAL_TYPE_ using real_t = double; #else using real_t = float; #endif // _REAL_TYPE_ void myMatrixFMA::Add_Mul_Matrix(ind_t inPos, const myMatrix &inM1, const myMatrix &inM2, ind_t inCol) { for (ind_t k = 0; k < inM2.m_Size_Y; ++k) { const auto &m0 = inM1.m_Array[k]; #ifdef _REAL_TYPE_ __m256d *_target = (__m256d *) (m_Array[inPos]); __m256d *_source = (__m256d *) (m0); const real_t &inD = inM2.m_Array[inCol][k]; const __m256d _d = _mm256_set1_pd(inD); for (ind_t indY = 0; indY < indSum4; ++indY) { *_target = _mm256_fmadd_pd(*(_source++), _d, *_target); ++_target; } // for #else __m256 *_target = (__m256 *) (m_Array[inPos]); __m256 *_source = (__m256 *) (m0); const real_t &inD = inM2.m_Array[inCol][k]; const __m256 _d = _mm256_set1_ps(inD); for (ind_t indY = 0; indY < indSum2; ++indY) { *_target = _mm256_fmadd_ps(*(_source++), _d, *_target); ++_target; } // if #endif // _REAL_TYPE_ for (ind_t indY = roundSize2; indY < m_Size_Y; ++indY) m_Array[inPos][indY] += m0[indY] * inD; } // for } |
Сообщ.
#5
,
|
|
|
Цитата a_n_y_a @ Править текст программы 200 файлов не хотелось бы. Существует ли способ решения этой задачи? Существуют программы для массового изменения файлов. Например, TextReplacer. Не обязательно корректировать тип переменных. Там, где это допустимо, можно применить преобразования типов. Чтобы не было проблемы "200 файлов", надо создавать проект с двумя сборками. И возникающие проблемы решать сразу. |
Сообщ.
#6
,
|
|
|
Спасибо, работает. Мне в 32 битном приложении, при получении длины файла типа ULONGLONG, надо работать с выделенным буфером по NEW, который принимает переменную типа UINT. И надо проверить не превышает ли длина файла максимально возможной длины буфера. Для этого есть константа INT_MAX. Но эта константа соответствует только 32-х битному проекту. Для 64 бит, эта константа остается той же. Существуют ранги для типов переменных, но хотелось бы работать с виндузовыми константами. Ты знаешь что-нибудь про это?
Добавлено Цитата ЫукпШ @ Цитата a_n_y_a @ Править текст программы 200 файлов не хотелось бы. Существует ли способ решения этой задачи? Существуют программы для массового изменения файлов. Например, TextReplacer. В среде VC++ 2017 года есть в меню такая же функция. Вопрос перехода с 32 на 64 возник недавно, вот я и спрашиваю. Пока изучаю вопрос. Спасибо за внимание ко мне. |
Сообщ.
#7
,
|
|
|
new принимает size_t. Откуда вообще взялась проблема с несоответствием типов? Тип объекта однозначно определяет его свойства. Разные типы – разные свойства. Любой каст означает смену свойств объекта. Иногда это надо, но хороший вопрос – как так получилось, что программе такое требуется постоянно?
|
Сообщ.
#8
,
|
|
|
Цитата Qraizer @ Откуда вообще взялась проблема с несоответствием типов? Есть переменная int A; Переменная может принимать отрицательное значение, и ей присваивается значение количества элементов в векторе: vector<...> V; A=V.size(); Вот тут и проблема, преобразования size_t (unsigned int) в int. У них разные диапазоны. Я написал функцию преобразования size_t в int: int IzSIZE_T__to__int(size_t R) { if (R > INT_MAX) { CMyThrowSize_t__to__int th; throw(th); return(-1); } else { return((int)R); }; }; и class CMyThrowSize_t__to__int:public std::exception { public: CMyThrowSize_t__to__int() {}; ~CMyThrowSize_t__to__int() {}; }; Проверял в тестовом проекте, функция работает, исключение создается и обрабатывается. Но у меня рабочий проект MDI, вызов throw происходит в просмотре. В каком месте текста программы (класса) надо написать блок try{}? Что-то я не пойму. |
Сообщ.
#9
,
|
|
|
Цитата a_n_y_a @ Ещё раз спросить? Ок. Переменная может принимать отрицательное значение, и ей присваивается значение количества элементов в векторе: |
Сообщ.
#10
,
|
|
|
Переменную int A я привел для примера. В проекте переменная А работает в алгоритме, и в некоторых случаях ей присваивается значение количества элементов в векторе. Но в других ветках алгоритма, этой переменной присваивается -1, и это значение имеет конкретный смысл.
По поводу преобразования size_t в int. Эта проблема шире, чем я описал. Например такой код: ...::OnPaint() { ... CRect r; GetClientRect(r); vector <CPoint> mp; mp.push_back(CPoint(r.left, r.top)); mp.push_back(CPoint(r.right, r.top)); mp.push_back(CPoint(r.right, r.bottom)); mp.push_back(CPoint(r.left, r.bottom)); mp.push_back(CPoint(r.left, r.top)); dc.Polyline(&(mp[0]), IzSIZE_T__to__int(mp.size())); ... }; Функция Polyline принимает в параметрах количество элементов массива типа int. Чтобы не создавать массив типа CPoint mp[3]; И не указывать количество элементов массива числом, я работаю с вектором. Конечно можно было бы написать: dc.Polyline(&(mp[0]), (int)mp.size()); Но в этом случае транслятор выдает предупреждение об ошибке при преобразовании типов. А я очень не люблю предупреждений. И программа с таким кодом будет не защищена от ошибок в процессе выполнения. Почему программа имеет десятки, если не сотни, подобных странных проектных решений? - Все дело в том, что программа разрабатывалась много лет. Это не коммерческая программа. Сейчас я чищу в программе все слабые места. С функцией преобразования size_t в int программа будет более защищенной. Просто раньше я использовал вариант (int)mp.size(). Теперь решил написать IzSIZE_T__to__int(mp.size()). |
Сообщ.
#11
,
|
|
|
Цитата a_n_y_a @ В проекте переменная А работает в алгоритме, и в некоторых случаях ей присваивается значение количества элементов в векторе. А в других случаях что? Такое ощущение, что одна и та же переменная в памяти, используется в разных местах для разных целей. |
Сообщ.
#12
,
|
|
|
Походу это некий признак ошибки. Ну, да, часто возникает навязчивое желание не делать статус операции отдельным атрибутом, а как-нибудь замешать в inside boundary уже имеющегося атрибута. Проблемы, когда это невозможно, неизбежны.
Добавлено P.S. Не стоит никогда так проектировать логику кода. Недаром практически во всех code style standard присутствует правило, запрещающее использование одной и той же переменной для различных целей. Хранить размер и одновременно признак ошибки как раз такой случай. Ну и никогда не следует смешивать типы данных по назначению. Какие свойства сущности нужны, вот такой тип данных и используем. Размер – значит size_t. Символ-байт – значит char. Число-байт – значит signed char. Итп. Но вообще проблема шире. У меня вот, только что глянул, есть проект на 120к кода. При переносе с 32-х бит на 64 проблема возникла только в двух аспектах, и обе были связаны с изменившимся inside boundary range для size_t. Один из-за DWORD в использовавшихся функциях и структурах Win32, второй из-за 32-битности MS Office SDK, принимающего int через VARIANT. Проблема была решена путём написанного на коленке простенького safe_cast<> в точечных местах, общим числом в пять штук. Никаких десятков предупреждений и массового рефакторинга. |