До сих пор везде использовал 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 и не может показать его определение.
Продвижение своими сайтами как стратегия роста и независимости