C# 与 C 类型对照速查表一、基础数值类型无符号 / 有符号整数C/C 原生类型Windows 宏别名占用字节C# 对应类型说明charCHAR1sbyte / bytechar 有符号unsigned char byteunsigned charUCHAR, BYTE1byteBYTEunsigned char0~255shortSHORT2short16 位有符号unsigned shortUSHORT, WORD2ushortWORD0~65535intINT4int32 位有符号unsigned intUINT4uint32 位无符号longLONG4intWindows 下 long 固定 4 字节unsigned longULONG, DWORD4uintDWORDULONG 0~0xFFFFFFFFlong longLONGLONG8long64 位有符号unsigned long longULONGLONG, DWORDLONG8ulong64 位无符号大容量数值floatFLOAT4float单精度浮点doubleDOUBLE8double双精度浮点特殊常量对照INVALID_FILE_ATTRIBUTES (DWORD)-1→ C#public const uint INVALID_FILE_ATTRIBUTES 0xFFFFFFFF;INVALID_HANDLE_VALUE (HANDLE)-1→ C#IntPtr(-1)二、句柄、指针类内核对象 / 内存地址C/C 类型含义C# 类型使用说明void*通用指针IntPtr万能指针存放地址HANDLE内核对象句柄文件、线程、进程、事件IntPtrCreateFile、OpenProcess 返回HMODULEDLL/EXE 模块句柄IntPtrLoadLibrary 返回HWND窗口句柄IntPtrFindWindow、MessageBox 窗口参数HDC绘图设备上下文IntPtrGDI 绘图 APIHBITMAP / HPEN / HBRUSHGDI 资源句柄IntPtr位图、画笔、画刷HINSTANCE程序实例句柄IntPtr等价 HMODULELPVOID / LPCVOID通用读写缓冲区指针IntPtr / byte[]ReadFile/WriteFile 数据缓冲区LPVOID*指针的指针out IntPtr输出句柄、输出指针关键规则所有句柄统一用IntPtr不用int/uint64 位程序地址会溢出无效句柄判断if (h IntPtr.Zero || h (IntPtr)(-1))。三、字符串类型ANSI / Unicode 宽字符重点易错C/C 类型编码C# 入参类型C# 输出参数DllImport CharSet 配置LPCSTR / LPSTRGBK ANSI 单字节stringStringBuilderCharSet.AnsiLPCWSTR / LPWSTRUTF16 宽字符xxxWstringStringBuilderCharSet.UnicodeTCHAR / LPTSTR自适应stringStringBuilderCharSet.Auto重点说明输入字符串单纯传入路径 / 文本用string输出字符串API 填充缓冲区不能用 string必须StringBuilder 例GetModuleFileNameW、GetWindowTextWGetProcAddress 函数名参数是 ANSI[DllImport(..., CharSet.Ansi)]。四、布尔类型C/C说明C# 类型注意BOOLint 底层TRUE1FALSE0bool / int推荐 bool非 0 自动 trueBOOLEANBYTE 1 字节布尔byte极少 API 使用五、函数指针 / 回调DLL 动态调用、窗口回调C 写法typedef int (WINAPI *MsgBoxPtr)(HWND hWnd, LPCWSTR txt, LPCWSTR cap, UINT type);C# 对应规则用delegate定义必须加特性[UnmanagedFunctionPointer(CallingConvention.StdCall)]Windows API 统一StdCall调用约定漏写会栈崩溃。表格C 类型C# 实现WINAPI 函数指针标记 StdCall 的 delegateLPVOID lpCallbackIntPtr / delegateC#[UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate int DlgMsgBox(IntPtr hWnd, string text, string cap, uint type);C#IntPtr pFunc GetProcAddress(hMod, MessageBoxW); DlgMsgBox fn Marshal.GetDelegateForFunctionPointerDlgMsgBox(pFunc);六、结构体 / 联合体Windows 常用大结构通用映射规则C# 结构体加[StructLayout(LayoutKind.Sequential)]保持内存顺序有指针 / 句柄成员一律用IntPtr字符数组缓冲区用fixed byte[]或StringBuilderC 结构示例C# 处理方案LARGE_INTEGER联合体高低位long直接用 ulong/long 替代 QuadPartOVERLAPPED 异步 IO 结构体自定义 StructSequential 布局SECURITY_ATTRIBUTES自定义结构体nLength 必须赋值LARGE_INTEGER 简化对照最常用Ctypedef union _LARGE_INTEGER { struct { DWORD LowPart; LONG HighPart; }; LONGLONG QuadPart; } LARGE_INTEGER;C# 直接简化// GetFileSizeEx 直接传 out long 替代结构体 [DllImport(kernel32.dll)] public static extern bool GetFileSizeEx(IntPtr hFile, out long lpFileSize);七、指针输出参数带 LP 前缀输出值C 原型BOOL GetXXX(DWORD* outValue);C 参数C# 修饰符示例LPDWORD / DWORD*out uintout uint dwOutLPULONGLONG / ULONGLONG*out ulongout ulong llOutLPHANDLE / HANDLE*out IntPtrout IntPtr hOutLPBOOL / BOOL*out boolout bool bRetcBOOL GetDiskFreeSpaceEx(LPCWSTR path, ULARGE_INTEGER* avail, ULARGE_INTEGER* total, ULARGE_INTEGER* free);C#[DllImport(kernel32.dll, CharSet CharSet.Unicode)] public static extern bool GetDiskFreeSpaceEx(string path, out long avail, out long total, out long free);八、调用约定对照表C 宏调用约定C# 委托标记使用场景WINAPI / __stdcallStdCallCallingConvention.StdCall所有 Windows 系统 API默认__cdeclCdeclCallingConvention.CdeclC 标准库、第三方自定义 DLL九、高频易错坑总结DWORD 不要用 int无符号数值超过 21 亿会溢出统一 uint句柄禁止用 int/long64 位程序地址超 32 位必须 IntPtr输出字符串不用 string只用 StringBuilder宽字符 API 统一CharSet.Unicode解决中文路径乱码函数指针委托必须指定 StdCall否则程序直接崩溃结构体不加 Sequential 会内存对齐错乱读取数据错误LoadLibrary / CreateFile 路径传中文必须 W 版本 Unicode 字符集。C# 使用[DllImport]引入原生 Win32 API分宽字符 W 版本推荐支持中文路径一、基础知识点[DllImport(kernel32.dll)]从系统内核库导入 APICharSet CharSet.Unicode 调用 xxxW 宽字符版本避免中文乱码StringBuilder作为输出字符串缓冲区C# string 不可修改不能当输出参数IntPtr对应 C/C 里HMODULE / HANDLE / void*1. GetModuleFileNameW C# 实现获取程序自身路径using System; using System.Text; using System.Runtime.InteropServices; class Win32Helper { // 导入API [DllImport(kernel32.dll, CharSet CharSet.Unicode)] public static extern uint GetModuleFileNameW( IntPtr hModule, // NULL0 取当前EXE StringBuilder lpFilename, uint nSize ); static void Main() { StringBuilder sbPath new StringBuilder(1024); uint ret GetModuleFileNameW(IntPtr.Zero, sbPath, (uint)sbPath.Capacity); if (ret 0) { Console.WriteLine(程序完整路径 sbPath.ToString()); // 截取目录去掉exe文件名 string dir System.IO.Path.GetDirectoryName(sbPath.ToString()); Console.WriteLine(程序目录 dir); } else { Console.WriteLine(获取失败); } Console.ReadKey(); } }2. LoadLibraryW GetProcAddress FreeLibrary C# 动态调用 DLL模拟 C 里动态加载 user32 调用 MessageBoxWusing System; using System.Runtime.InteropServices; class DllInvokeDemo { // 1. 加载释放DLL [DllImport(kernel32.dll, CharSet CharSet.Unicode)] public static extern IntPtr LoadLibraryW(string lpLibFileName); [DllImport(kernel32.dll, CharSet CharSet.Ansi)] // 函数名是ASCII public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName); [DllImport(kernel32.dll)] public static extern bool FreeLibrary(IntPtr hModule); // 2. 定义MessageBoxW委托对应C函数指针 [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate int DlgMsgBox(IntPtr hWnd, string text, string caption, uint type); static void Main() { // 加载user32.dll IntPtr hUser32 LoadLibraryW(user32.dll); if (hUser32 IntPtr.Zero) { Console.WriteLine(加载DLL失败); return; } // 获取MessageBoxW地址 IntPtr pMsgBox GetProcAddress(hUser32, MessageBoxW); if (pMsgBox IntPtr.Zero) { FreeLibrary(hUser32); return; } // 转为委托调用 DlgMsgBox msgBox Marshal.GetDelegateForFunctionPointerDlgMsgBox(pMsgBox); msgBox(IntPtr.Zero, C#调用Win32 API弹窗, 提示, 0); // 释放库 FreeLibrary(hUser32); Console.ReadKey(); } }3. 常用配套 API 补充GetFileAttributesW / INVALID_FILE_ATTRIBUTESpublic const uint INVALID_FILE_ATTRIBUTES 0xFFFFFFFF; [DllImport(kernel32.dll, CharSet CharSet.Unicode)] public static extern uint GetFileAttributesW(string lpFileName); // 使用 uint attr GetFileAttributesW(D:\test.txt); if (attr INVALID_FILE_ATTRIBUTES) { Console.WriteLine(文件不存在/无法访问); } else { bool isHidden (attr 2) ! 0; // FILE_ATTRIBUTE_HIDDEN 2 Console.WriteLine(是否隐藏 isHidden); }关键注意事项CharSet.Unicode 必须加不加默认 Ansi中文路径、中文参数会乱码。输出字符串不能用string必须StringBuilder原生 API 要改写缓冲区string 是只读。函数名参数GetProcAddress传 ANSI 字符串 导出函数名字符串固定 ASCII所以[DllImport]写CharSet.Ansi。委托必须标记[UnmanagedFunctionPointer(CallingConvention.StdCall)]Windows API 统一__stdcall 调用约定漏写会栈失衡崩溃。资源释放LoadLibrary后必须FreeLibrary避免内存泄漏。4. C# 与 C 类型对照速查表C/C 类型C# 对应类型HMODULE / HANDLEIntPtrDWORDuintLPCWSTR / LPWSTRstring / StringBuilderWINAPI 函数指针delegate Marshal.GetDelegateForFunctionPointerBOOLbool
C# 与 C 类型对照速查表
C# 与 C 类型对照速查表一、基础数值类型无符号 / 有符号整数C/C 原生类型Windows 宏别名占用字节C# 对应类型说明charCHAR1sbyte / bytechar 有符号unsigned char byteunsigned charUCHAR, BYTE1byteBYTEunsigned char0~255shortSHORT2short16 位有符号unsigned shortUSHORT, WORD2ushortWORD0~65535intINT4int32 位有符号unsigned intUINT4uint32 位无符号longLONG4intWindows 下 long 固定 4 字节unsigned longULONG, DWORD4uintDWORDULONG 0~0xFFFFFFFFlong longLONGLONG8long64 位有符号unsigned long longULONGLONG, DWORDLONG8ulong64 位无符号大容量数值floatFLOAT4float单精度浮点doubleDOUBLE8double双精度浮点特殊常量对照INVALID_FILE_ATTRIBUTES (DWORD)-1→ C#public const uint INVALID_FILE_ATTRIBUTES 0xFFFFFFFF;INVALID_HANDLE_VALUE (HANDLE)-1→ C#IntPtr(-1)二、句柄、指针类内核对象 / 内存地址C/C 类型含义C# 类型使用说明void*通用指针IntPtr万能指针存放地址HANDLE内核对象句柄文件、线程、进程、事件IntPtrCreateFile、OpenProcess 返回HMODULEDLL/EXE 模块句柄IntPtrLoadLibrary 返回HWND窗口句柄IntPtrFindWindow、MessageBox 窗口参数HDC绘图设备上下文IntPtrGDI 绘图 APIHBITMAP / HPEN / HBRUSHGDI 资源句柄IntPtr位图、画笔、画刷HINSTANCE程序实例句柄IntPtr等价 HMODULELPVOID / LPCVOID通用读写缓冲区指针IntPtr / byte[]ReadFile/WriteFile 数据缓冲区LPVOID*指针的指针out IntPtr输出句柄、输出指针关键规则所有句柄统一用IntPtr不用int/uint64 位程序地址会溢出无效句柄判断if (h IntPtr.Zero || h (IntPtr)(-1))。三、字符串类型ANSI / Unicode 宽字符重点易错C/C 类型编码C# 入参类型C# 输出参数DllImport CharSet 配置LPCSTR / LPSTRGBK ANSI 单字节stringStringBuilderCharSet.AnsiLPCWSTR / LPWSTRUTF16 宽字符xxxWstringStringBuilderCharSet.UnicodeTCHAR / LPTSTR自适应stringStringBuilderCharSet.Auto重点说明输入字符串单纯传入路径 / 文本用string输出字符串API 填充缓冲区不能用 string必须StringBuilder 例GetModuleFileNameW、GetWindowTextWGetProcAddress 函数名参数是 ANSI[DllImport(..., CharSet.Ansi)]。四、布尔类型C/C说明C# 类型注意BOOLint 底层TRUE1FALSE0bool / int推荐 bool非 0 自动 trueBOOLEANBYTE 1 字节布尔byte极少 API 使用五、函数指针 / 回调DLL 动态调用、窗口回调C 写法typedef int (WINAPI *MsgBoxPtr)(HWND hWnd, LPCWSTR txt, LPCWSTR cap, UINT type);C# 对应规则用delegate定义必须加特性[UnmanagedFunctionPointer(CallingConvention.StdCall)]Windows API 统一StdCall调用约定漏写会栈崩溃。表格C 类型C# 实现WINAPI 函数指针标记 StdCall 的 delegateLPVOID lpCallbackIntPtr / delegateC#[UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate int DlgMsgBox(IntPtr hWnd, string text, string cap, uint type);C#IntPtr pFunc GetProcAddress(hMod, MessageBoxW); DlgMsgBox fn Marshal.GetDelegateForFunctionPointerDlgMsgBox(pFunc);六、结构体 / 联合体Windows 常用大结构通用映射规则C# 结构体加[StructLayout(LayoutKind.Sequential)]保持内存顺序有指针 / 句柄成员一律用IntPtr字符数组缓冲区用fixed byte[]或StringBuilderC 结构示例C# 处理方案LARGE_INTEGER联合体高低位long直接用 ulong/long 替代 QuadPartOVERLAPPED 异步 IO 结构体自定义 StructSequential 布局SECURITY_ATTRIBUTES自定义结构体nLength 必须赋值LARGE_INTEGER 简化对照最常用Ctypedef union _LARGE_INTEGER { struct { DWORD LowPart; LONG HighPart; }; LONGLONG QuadPart; } LARGE_INTEGER;C# 直接简化// GetFileSizeEx 直接传 out long 替代结构体 [DllImport(kernel32.dll)] public static extern bool GetFileSizeEx(IntPtr hFile, out long lpFileSize);七、指针输出参数带 LP 前缀输出值C 原型BOOL GetXXX(DWORD* outValue);C 参数C# 修饰符示例LPDWORD / DWORD*out uintout uint dwOutLPULONGLONG / ULONGLONG*out ulongout ulong llOutLPHANDLE / HANDLE*out IntPtrout IntPtr hOutLPBOOL / BOOL*out boolout bool bRetcBOOL GetDiskFreeSpaceEx(LPCWSTR path, ULARGE_INTEGER* avail, ULARGE_INTEGER* total, ULARGE_INTEGER* free);C#[DllImport(kernel32.dll, CharSet CharSet.Unicode)] public static extern bool GetDiskFreeSpaceEx(string path, out long avail, out long total, out long free);八、调用约定对照表C 宏调用约定C# 委托标记使用场景WINAPI / __stdcallStdCallCallingConvention.StdCall所有 Windows 系统 API默认__cdeclCdeclCallingConvention.CdeclC 标准库、第三方自定义 DLL九、高频易错坑总结DWORD 不要用 int无符号数值超过 21 亿会溢出统一 uint句柄禁止用 int/long64 位程序地址超 32 位必须 IntPtr输出字符串不用 string只用 StringBuilder宽字符 API 统一CharSet.Unicode解决中文路径乱码函数指针委托必须指定 StdCall否则程序直接崩溃结构体不加 Sequential 会内存对齐错乱读取数据错误LoadLibrary / CreateFile 路径传中文必须 W 版本 Unicode 字符集。C# 使用[DllImport]引入原生 Win32 API分宽字符 W 版本推荐支持中文路径一、基础知识点[DllImport(kernel32.dll)]从系统内核库导入 APICharSet CharSet.Unicode 调用 xxxW 宽字符版本避免中文乱码StringBuilder作为输出字符串缓冲区C# string 不可修改不能当输出参数IntPtr对应 C/C 里HMODULE / HANDLE / void*1. GetModuleFileNameW C# 实现获取程序自身路径using System; using System.Text; using System.Runtime.InteropServices; class Win32Helper { // 导入API [DllImport(kernel32.dll, CharSet CharSet.Unicode)] public static extern uint GetModuleFileNameW( IntPtr hModule, // NULL0 取当前EXE StringBuilder lpFilename, uint nSize ); static void Main() { StringBuilder sbPath new StringBuilder(1024); uint ret GetModuleFileNameW(IntPtr.Zero, sbPath, (uint)sbPath.Capacity); if (ret 0) { Console.WriteLine(程序完整路径 sbPath.ToString()); // 截取目录去掉exe文件名 string dir System.IO.Path.GetDirectoryName(sbPath.ToString()); Console.WriteLine(程序目录 dir); } else { Console.WriteLine(获取失败); } Console.ReadKey(); } }2. LoadLibraryW GetProcAddress FreeLibrary C# 动态调用 DLL模拟 C 里动态加载 user32 调用 MessageBoxWusing System; using System.Runtime.InteropServices; class DllInvokeDemo { // 1. 加载释放DLL [DllImport(kernel32.dll, CharSet CharSet.Unicode)] public static extern IntPtr LoadLibraryW(string lpLibFileName); [DllImport(kernel32.dll, CharSet CharSet.Ansi)] // 函数名是ASCII public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName); [DllImport(kernel32.dll)] public static extern bool FreeLibrary(IntPtr hModule); // 2. 定义MessageBoxW委托对应C函数指针 [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate int DlgMsgBox(IntPtr hWnd, string text, string caption, uint type); static void Main() { // 加载user32.dll IntPtr hUser32 LoadLibraryW(user32.dll); if (hUser32 IntPtr.Zero) { Console.WriteLine(加载DLL失败); return; } // 获取MessageBoxW地址 IntPtr pMsgBox GetProcAddress(hUser32, MessageBoxW); if (pMsgBox IntPtr.Zero) { FreeLibrary(hUser32); return; } // 转为委托调用 DlgMsgBox msgBox Marshal.GetDelegateForFunctionPointerDlgMsgBox(pMsgBox); msgBox(IntPtr.Zero, C#调用Win32 API弹窗, 提示, 0); // 释放库 FreeLibrary(hUser32); Console.ReadKey(); } }3. 常用配套 API 补充GetFileAttributesW / INVALID_FILE_ATTRIBUTESpublic const uint INVALID_FILE_ATTRIBUTES 0xFFFFFFFF; [DllImport(kernel32.dll, CharSet CharSet.Unicode)] public static extern uint GetFileAttributesW(string lpFileName); // 使用 uint attr GetFileAttributesW(D:\test.txt); if (attr INVALID_FILE_ATTRIBUTES) { Console.WriteLine(文件不存在/无法访问); } else { bool isHidden (attr 2) ! 0; // FILE_ATTRIBUTE_HIDDEN 2 Console.WriteLine(是否隐藏 isHidden); }关键注意事项CharSet.Unicode 必须加不加默认 Ansi中文路径、中文参数会乱码。输出字符串不能用string必须StringBuilder原生 API 要改写缓冲区string 是只读。函数名参数GetProcAddress传 ANSI 字符串 导出函数名字符串固定 ASCII所以[DllImport]写CharSet.Ansi。委托必须标记[UnmanagedFunctionPointer(CallingConvention.StdCall)]Windows API 统一__stdcall 调用约定漏写会栈失衡崩溃。资源释放LoadLibrary后必须FreeLibrary避免内存泄漏。4. C# 与 C 类型对照速查表C/C 类型C# 对应类型HMODULE / HANDLEIntPtrDWORDuintLPCWSTR / LPWSTRstring / StringBuilderWINAPI 函数指针delegate Marshal.GetDelegateForFunctionPointerBOOLbool