До сих пор везде использовал size_t
, считая что это целочисленный тип, который адаптируется под разрядность операционной системы (4 байта - для x86, 8 - для x64). И вот для работы с WriteProcessMemory
я так же пытался использовать size_t*
в качестве последнего аргумента SIZE_T *lpNumberOfBytesWritten
- на что получил:
invalid conversion from 'size_t*' to 'SIZE_T*'
Перейдя к typedef-ам я обнаружил следующее для SIZE_T:
typedef ULONG_PTR SIZE_T, *PSIZE_T;
typedef unsigned long ULONG_PTR, *PULONG_PTR;
причем последняя строка была внутри какого-то #if
с комментарием
/* !_WIN64 */
и следующее для size_t
:
typedef __SIZE_TYPE__ size_t;
где __SIZE_TYPE__
, видимо, какой-то макрос (автопереход к нему у меня не работает).
Правильно я понимаю, что они по сути своей идентичны и не зря имеют одинаковое именование, а эта ошибка - лишь формальность, вызванная различием их реализаций?
На моём экземпляре Visual Studio 2017 следующий код даёт такой вывод при различной разрядности проекта:
#include <iostream>
#include <typeinfo>
#include <BaseTsd.h>
#include <cstddef>
int main()
{
std::cout << typeid(SIZE_T).name() << "\n" <<
typeid(size_t).name() << "\n";
}
32 bit
unsigned long
unsigned int
64 bit
unsigned __int64
unsigned __int64
Можно заметить, что на 64 разрядной платформе эти типы идентичны. В то же время на 32 разрядной типы хоть и различны (с точки зрения языка), но представляют одинаковый набор возможных значений, т.е. sizeof(int) == sizeof(long)
в Windows, хотя в общем случае это не всегда так. Но даже несмотря на совпадение размеров различные типы не всегда совместимы (иначе бы не было ошибки, с которой вы сюда пришли). И, например, следующий код будет корректным для x86, но вызовет ошибку компиляции для x64:
void f(size_t) {}
void f(SIZE_T) {}
Если же посмотреть на описание типов, то можно увидеть следующее:
SIZE_T
The maximum number of bytes to which a pointer can point. Use for a count that must span the full range of a pointer.
This type is declared in BaseTsd.h as follows:
typedef ULONG_PTR SIZE_T;
size_t
The type size_t
is an implementation-defined unsigned integer type that is large enough to contain the size in bytes of any object ([expr.sizeof]).
По сути, разными словами выражено одно и то же - "тип, позволяющий хранить размер максимально возможного объекта". При этом для size_t
беззнаковость указана явно, а вот для SIZE_T
она лишь косвенно проскакивает через букву U
в ULONG_PTR
.
Общий совет такой: если работаете с WinAPI и имеется параметр типа SIZE_T
, то этот тип и стоит использовать, во всех остальных ситуациях - следует отдавать предпочтение стандартным типам C++ для увеличения уровня переносимости кода. Понятно, что на стыке двух миров придётся обеспечивать преобразование одного типа в другой. В хорошем решении этой задачи стык этот должен быть достаточно лаконичен и не размазан по всему коду.
Правильно я понимаю, что они по сути своей идентичны и незря имеют одинаковое именование, а эта ошибка - лишь формальность, вызванная различием их реализаций?
Да, они должны быть эквивалентны. (В том смысле, что оба беззнаковые, одинакового размера.)
size_t
(или std::size_t
) - это стандартный тип из <cstddef>
/<stddef.h>
. В своем коде лучше использовать именно его.
SIZE_T
- тип из WinAPI.
А тип __SIZE_TYPE__
скорее всего встроен в ваш компилятор, поэтому ваша IDE и не может показать его определение.
Виртуальный выделенный сервер (VDS) становится отличным выбором
Все источники говорят что, типы sigaction, sigset_t находятся в signalh Эта строчка у меня в самом верху присутствует:
Делаю колбэк на изменения размеров окна, и реагирования на изменение размера рендерераХорошо, объявил typedef, класс окна и класс рендерера...
После вставки носителя я получу сначала событие dbch_devicetype с deviceinterface, а затем с volume и если накопитель вставлялся 1, то очевидно оба события будут...
Доброе! Есть следющий код: