MFC中关于UINT与USHORT

本文详细解析了MFC中各种数据类型,包括UINT、USHORT、WORD等,并通过实例介绍了它们的应用场景。同时,还提供了不同类型之间的转换方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在C, C++中不存在UINT这个关键字, UINT类型是unsigned int 派生 出来的
int是带符号的,表示范围是:-2147483648 到 2147483647
uint是不带符号整形,表示范围是0到42949 67295(2^32-1),即第一个数字不表示符号
在C#中,uint 是关键字, 表示一种整型,该类型根据下表显示的大小和范围存储值。
MFC中定义UNIT:UINT A 16-bit unsigned integer on Windows versions 3.0 and 3.1; a 32-bit unsigned integer on Win32.在Win32中是一个32-bit 未带 正负号整数。
     MFC中定义USHORT:保存 16 位(双字节)无符号整数
在项目过程中,有个调用函数的定义:smc_line_unit(WORD ConnectNo,WORD Crd,WORD AxisNum,WORD* AxisList,double*Target_Pos,WORD posi_mode);这是一个直线插补的实现函数,虽然在API中已经定义,但是还是需要自己在库文件中重新定义这个函数,所以就没有模板可以直接写入变量。因为要对AxisList进行定义,我对MFC的了解不深,不太会调用WORD类型的数据,于是我找到了其中 ConnectNo的定义,希望可以从中找到WORD*的定义模式,看到的是这个:UINT m_iConnectNum;于是我定义AxisList的数据类型为UINT *AxisList。可是在编译过程中提示并不能这样匹配。我尝试了很多数据类型并查找资料,于是确定了该类的定义模式应该是 USHORT *AxisList。
看到了一些解释:1.ushort实际是一个宏,不是C标准数据类型。这应该可以在系统的头文件中找到相关的typedef定义。2.unsigned short。个人觉得第二种比较靠谱。
又找到关于WORD的解释:16-bit 整数 ,未带正负号。
所以这里对应的应该是USHORT而不是UINT。 注意在C#里面:USHORT只是UINT16的简写。
这里也附上有关一些数据在MFC中的对应类型汇总:
NULL            0
VOID            void

BOOL           int

CHAR           char
CCHAR         char
UCHAR        unsigned char
BYTE           unsigned char
WCHAR        wchar_t
_TCHAR        wchar_t
SHORT         short
WORD          unsigned short 
USHORT       unsigned short 
INT               int
UINT            unsigned int
LONG           long
DWORD       unsigned long
ULONG        unsigned long
LONGLONG  __int64
ULONGLONG unsigned __int64
FLOAT          float
DOUBLE       double


也附上博客大神的一些总结:
BOOL:布尔值,取值为TRUE or FALSE
BSTR:32-bit 字符指针
BYTE:8-bit整数,未带正负号
COLORREF:32-bit数值,代表一个颜色值
DWORD:32-bit整数,未带正负号
LONG:32-bit整数,带正负号
LPARAM:32-bit整数,作为窗口函数或callback函数的一个参数
LPCSTR:32-bit指针,指向一个常数字符串
LPSTR:32-bit指针,指向一个字符串
LPCTSTR:32-bit指针,指向一个常数字符串,此字符串可以移植到Unicode和DBCS
LPTSTR:32-bit指针,指向一个字符串,此字符串可以移植到Unicode和DBCS
LPVOID:32-bit指针,指向一个未指定类型的数据
LPRESULT:32-bit数值,作为窗口函数或callback函数的返回值
UINT:在Win16中是一个16-bit 未带正负号整数,在Win32中是一个32-bit 未带 正负号整数,
WNDPROC:32-bit指针,指向一个窗口函数
WORD:16-bit 整数 ,未带正负号
WPARAM:窗口函数或callback函数的一个参数,在Win16中是16-bit,在Win32中是32-bit

下面这些是MFC独特的数据类型
POSITION:一个数值,代表collection对象(例如数组或链表)中的元素位置,常 用于MFC collection classes(即数据处理类,如CArray)
LPCRECT:32-bit指针,指向一个不变的RECT结构 
L表示long指针, 这是为了兼容Windows 3.1等16位操作系统遗留下来的, 在win32中以及其他的32为操作系统中, long指针和near指针及far修饰符都是为了兼容的作用。没有实际意义。
P表示这是一个指针
C表示是一个常量
T在Win32环境中, 有一个_T宏, 这个宏用来表示你的字符是否使用UNICODE, 如果你的程序定义了UNICODE或者其他相关的宏, 那么这个字符或者字符串将被作为UNICODE字符串,否则就是标准的ANSI字符串。
STR表示这个变量是一个字符串。
所以LPCTSTR就表示一个指向常固定地址的可以根据一些宏定义改变语义的字符串。
同样, LPCSTR就只能是一个ANSI字符串, 在程序中我们大部分时间要使用带T的类型定义。
LPCTSTR == const TCHAR *
MFC/windows基本数据类型详细介绍
#define FALSE   0           afx.h
#define TRUE    1           afx.h
#define NULL    0           afx.h
typedef void                VOID        winnt.h
//短整型typedef unsigned short
typedef unsigned short      USHORT;     windef.h
typedef unsigned short      WORD;       windef.h
typedef unsigned short      wchar_t
typedef short               SHORT;      winnt.h
//整型typedef  int
typedef int                 BOOL;  //取值为TRUE or FALSE windef.h
typedef int                 INT; windef.h
typedef unsigned int        UINT; //定义一个新的Win32数据类型,它会把一个参数强制转换成Windows3.x应用中的16位值 或Win32应用中的32位值windef.h
//长整型typedef long
typedef unsigned long       ULONG;    windef.h
typedef unsigned long       DWORD;    windef.h
typedef DWORD               COLORREF; windef.h
typedef long                LONG;     winnt.h 
typedef __int64             LONGLONG; winnt.h
typedef unsigned __int64    ULONGLONG; winnt.h
typedef ULONGLONG           DWORDLONG; winnt.h
//浮点型
typedef float               FLOAT;     windef.h
typedef double              DOUBLE;    wtypes.h 
//字符类型typedef char
typedef char                CHAR/CCHAR; winnt.h
typedef unsigned char       UCHAR;      windef.h
typedef unsigned char       BYTE;       windef.h
typedef wchar_t             WCHAR; //声明一个16位的UNICODE字符,用来表示世界上所有已知的书写语言的符号winnt.h
//指向字符串的指针类型LP*
// UNICODE (Wide Character) types 
typedef wchar_t WCHAR;    // wc,   16-bit UNICODE character
typedef __nullterminated WCHAR *NWPSTR, *LPWSTR, *PWSTR; 
typedef __nullterminated CONST WCHAR *LPCWSTR, *PCWSTR;
// ANSI (Multi-byte Character) types
typedef CHAR *PCHAR, *LPCH, *PCH;
typedef __nullterminated CHAR *NPSTR, *LPSTR, *PSTR; 
//指向Windows字符串(以空字符结束)的32位指针char* 
typedef __nullterminated CONST CHAR *LPCSTR, *PCSTR; 
//指向Windows常字符串(以空字符结束)的32位指针const   char*
// Neutral ANSI/UNICODE types and macros
 
// tchar.h
#ifdef  _UNICODE
typedef wchar_t     _TCHAR;
typedef wchar_t     TCHAR;
#else  
typedef char            _TCHAR;
typedef char            TCHAR;
#endif  
 
typedef LPWSTR PTSTR, LPTSTR; 
//指向Windows字符串(以空字符结束)的32位指针,用于移植到双字节字符集 
LPTSTR   For   Unicode   platforms,it   is   LPWSTR,For   ANSI   and  DBCS   platforms,it   is  LPSTR  
typedef LPCWSTR            PCTSTR, LPCTSTR; 
//指向Windows常字符串(以空字符结束)的32位指针const char* ,用于移植到双字节字符集
LPCTSTR For   Unicode   platforms,it   is   LPCWSTR,For   ANSI   and   DBCS   platforms,it   is  LPCSTR   
typedef LPWSTR LP;
#define __T(x)      x        tchar.h  // ndef _UNICODE
#define _T(x)       __T(x)     tchar.h
#define _TEXT(x)    __T(x)     tchar.h
#define __TEXT(quote) L##quote winnt.h  // r_winnt  
//以上的_T、__T、_TEXT、__TEXT、L宏使字符串会自动根据工程的版本(ANSI还是UNICODE)进行转化.   使代码不需修改自动适应ASNI和UNICODE版本
typedef WCHAR OLECHAR;                        wtypes.h
typedef OLECHAR *BSTR;   unsigned   short*  wtypes.h
//函数参数、返回值类型
typedef UINT_PTR            WPARAM; //窗口函数或callback函数的一个参数,在Win16中是16-bit,在Win32中是32-bit windef.h
typedef LONG_PTR            LPARAM; //32位窗口函数或callback函数的一个参数windef.h
typedef LONG_PTR            LRESULT; //32位作为窗口函数或callback函数的返回值windef.h
//指向函数的指针类型
typedef int (WINAPI *PROC)();PROC //指向回调函数的指针
typedef LRESULT (CALLBACK* WNDPROC)(HWND, UINT, WPARAM, LPARAM);
//Windows函数调用类型__stdcall
#define CALLBACK    __stdcall   windef.h
#define WINAPI      __stdcall   windef.h
#define WINAPIV     __cdecl     windef.h
#define APIENTRY    WINAPI      windef.h
#define APIPRIVATE  __stdcall   windef.h
#define PASCAL      __stdcall   windef.h
// 关于调用宏参考http://blog.163.com/xiang_163_ok/blog/static/6171684520082161551829/
typedef void far            *LPVOID;  指向任意类型的指针windef.h
下面将介绍一些常用数据类型的使用:
我们先定义一些常见类型变量借以说明 
int   i   =   100; 
long   l   =   2001; 
float   f=300.2; 
double   d=12345.119; 
char   username[]="女侠程佩君"; 
char   temp[200]; 
char   *buf; 
CString   str; 
_variant_t   v1; 
_bstr_t   v2; 

一、其它数据类型转换为字符串 
短整型(int) 
itoa(i,temp,10);///将i转换为字符串放入temp中,最后一个数字表示十进制 
itoa(i,temp,2);   ///按二进制方式转换   
长整型(long) 
ltoa(l,temp,10); 

二、从其它包含字符串的变量中获取指向该字符串的指针 
CString变量 
str   =   "2008北京奥运"; 
buf   =   (LPSTR)(LPCTSTR)str;   
BSTR类型的_variant_t变量 
v1   =   (_bstr_t)"程序员"; 
buf   =   _com_util::ConvertBSTRToString((_bstr_t)v1); 

三、字符串转换为其它数据类型 
strcpy(temp,"123");   

短整型(int) 
i   =   atoi(temp);   
长整型(long) 
l   =   atol(temp);   
浮点(double) 
d   =   atof(temp); 

四、其它数据类型转换到CString 
使用CString的成员函数Format来转换,例如: 
整数(int) 
str.Format("%d",i);   
浮点数(float) 
str.Format("%f",i);   
字符串指针(char   *)等已经被CString构造函数支持的数据类型可以直接赋值 
str   =   username; 

五、BSTR、_bstr_t与CComBSTR 
CComBSTR、_bstr_t是对BSTR的封装,BSTR是指向字符串的32位指针。 
char   *转换到BSTR可以这样:   BSTR   b=_com_util::ConvertStringToBSTR("数据");///使用前需要加上头文件comutil.h 
反之可以使用char   *p=_com_util::ConvertBSTRToString(b); 

六、VARIANT   、_variant_t   与   COleVariant 
VARIANT的结构可以参考头文件VC98\Include\OAIDL.H中关于结构体tagVARIANT的定义。 
对于VARIANT变量的赋值:首先给vt成员赋值,指明数据类型,再对联合结构中相同数据类型的变量赋值,举个例子: 
VARIANT   va; 
int   a=2001; 
va.vt=VT_I4;///指明整型数据 
va.lVal=a;   ///赋值 

对于不马上赋值的VARIANT,最好先用Void   VariantInit(VARIANTARG   FAR*   pvarg);进行初始化,其本质是将vt设置为VT_EMPTY,下表我们列举vt与常用数据的对应关系: 

unsigned   char   bVal;   VT_UI1   
short   iVal;   VT_I2   
long   lVal;   VT_I4   
float   fltVal;   VT_R4   
double   dblVal;   VT_R8   
VARIANT_BOOL   boolVal;   VT_BOOL   
SCODE   scode;   VT_ERROR   
CY   cyVal;   VT_CY   
DATE   date;   VT_DATE   
BSTR   bstrVal;   VT_BSTR   
IUnknown   FAR*   punkVal;   VT_UNKNOWN   
IDispatch   FAR*   pdispVal;   VT_DISPATCH   
SAFEARRAY   FAR*   parray;   VT_ARRAY|*   
unsigned   char   FAR*   pbVal;   VT_BYREF|VT_UI1   
short   FAR*   piVal;   VT_BYREF|VT_I2   
long   FAR*   plVal;   VT_BYREF|VT_I4   
float   FAR*   pfltVal;   VT_BYREF|VT_R4   
double   FAR*   pdblVal;   VT_BYREF|VT_R8   
VARIANT_BOOL   FAR*   pboolVal;   VT_BYREF|VT_BOOL   
SCODE   FAR*   pscode;   VT_BYREF|VT_ERROR   
CY   FAR*   pcyVal;   VT_BYREF|VT_CY   
DATE   FAR*   pdate;   VT_BYREF|VT_DATE   
BSTR   FAR*   pbstrVal;   VT_BYREF|VT_BSTR   
IUnknown   FAR*   FAR*   ppunkVal;   VT_BYREF|VT_UNKNOWN   
IDispatch   FAR*   FAR*   ppdispVal;   VT_BYREF|VT_DISPATCH   
SAFEARRAY   FAR*   FAR*   pparray;   VT_ARRAY|*   
VARIANT   FAR*   pvarVal;   VT_BYREF|VT_VARIANT   
void   FAR*   byref;   VT_BYREF   

_variant_t是VARIANT的封装类,其赋值可以使用强制类型转换,其构造函数会自动处理这些数据类型。 
例如: 
long   l=222; 
int   i=100; 
_variant_t   lVal(l); 
lVal   =   (long)i; 

COleVariant的使用与_variant_t的方法基本一样,请参考如下例子: 
COleVariant   v3   =   "字符串",   v4   =   (long)1999; 
CString   str   =(BSTR)v3.pbstrVal; 
long   i   =   v4.lVal; 

七、其它 
对消息的处理中我们经常需要将WPARAM或LPARAM等32位数据(DWORD)分解成两个16位数据(WORD),例如: 
LPARAM   lParam; 
WORD   loValue   =   LOWORD(lParam);///取低16位 
WORD   hiValue   =   HIWORD(lParam);///取高16位   
对于16位的数据(WORD)我们可以用同样的方法分解成高低两个8位数据(BYTE),例如: 
WORD   wValue; 
BYTE   loValue   =   LOBYTE(wValue);///取低8位 
BYTE   hiValue   =   HIBYTE(wValue);///取高8位 


<think>根据用户的上一个问题,用户想知道如何计算C#枚举类型中最大的ID值(即枚举成员的最大整数值)。回顾引用内容,引用[3]提到了枚举的定义示例,其中每个成员有显式赋值,而引用[4]则展示了带有Description属性的枚举。分析:在C#枚举中,每个枚举成员都有一个底层整数值(默认为int),可以是显式赋值或隐式赋值(从0开始递增)。要获取枚举的最大ID值,实际上是获取所有枚举成员的底层整数值中的最大值。由于枚举类型是值类型,我们可以通过以下步骤实现:1.获取枚举的所有成员名称数组(Enum.GetNames)或成员值数组(Enum.GetValues)。2.将这些枚举值转换为底层整数(转换为int或long)。3.使用LINQ的Max方法或循环比较找出最大值。注意:枚举的底层类型可以是byte,sbyte,short,ushort,int,uint,long,ulong,但通常使用int。为确保通用性,可以转换为long(以避免溢出)后再比较。方法1:使用Enum.GetValues配合Cast和Max方法2:使用循环遍历比较引用[1]中展示了如何将int转换为枚举值,而引用[2]则展示了如何从枚举值获取整数(通过强制转换)。因此,我们可以这样写:```###C#枚举最大ID值计算方法要获取枚举类型的最大整数值(MaxID),可通过以下三种方法实现:####1.LINQ快速查询(推荐)```csharpusingSystem;usingSystem.Linq;publicenumTestType{None=0,WaitTest=2,Testing=3,WaitCheck=4,Finished=5}classProgram{staticvoidMain(){//获取所有枚举值的整数形式longmaxID=Enum.GetValues(typeof(TestType)).Cast<TestType>().Max(value=>(long)value);Console.WriteLine($"MaxID={maxID}");//输出:MaxID=5}}```>💡使用`(long)`转换避免整数溢出[^3]####2.传统循环遍历```csharppublicstaticlongGetMaxEnumValue(TypeenumType){longmax=long.MinValue;foreach(varvalueinEnum.GetValues(enumType)){longcurrent=Convert.ToInt64(value);if(current>max)max=current;}returnmax;}//调用:longmaxID=GetMaxEnumValue(typeof(TestType));```####3.动态底层类型转换```csharp//自动适应枚举的底层数据类型publicstaticdynamicGetMaxEnumValueSmart(TypeenumType){Arrayvalues=Enum.GetValues(enumType);TypeunderlyingType=Enum.GetUnderlyingType(enumType);dynamicmax=Convert.ChangeType(values.GetValue(0),underlyingType);foreach(varvalueinvalues){dynamiccurrent=Convert.ChangeType(value,underlyingType);if(current>max)max=current;}returnmax;}```>⚠️**重要边界情况处理**>-**空枚举**:若枚举无成员(不常见但需防御),应抛出异常:>```csharp>if(!values.Any())thrownewInvalidOperationException("枚举类型不包含任何成员");>```>-**负值处理**:部分枚举可能包含负数(如`Error=-1`),上述方法仍有效>-**标志枚举(Flags)**:同样适用,例如`FileAccess.ReadWrite=3`会被正确计算---###数学原理设枚举$E$有$n$个成员,对应的整数值为集合$\{v_0,v_1,\dots,v_{n-1}\}$,则$$\text{MaxID}=\max_{k\in[0,n-1]}v_k$$当存在复合标志(如`ReadWrite=Read|Write`)时,最大ID值等于各成员的最大整数值(而非位或结果)[^4]。---###应用场景1.**数据库存储优化**:根据MaxID预分配字段长度2.**序列化验证**:确保外部输入值不超过枚举范围3.**位标志校验**:验证组合值是否合法---§§相关问题§1.如何获取枚举成员的数量?2.枚举的底层类型如何更改?3.如何判断一个整数是否在枚举定义的范围内?4.标志枚举(FlagsAttribute)的最大值如何计算?</think> ### C# 枚举类型 MaxID 值计算方法 在 C# 中,获取枚举类型的 **MaxID**(最大整数值)有以下三种核心方法: #### 1. LINQ 快捷查询法(推荐) ```csharp public enum TestType { None = 0, WaitTest = 2, Testing = 3, WaitCheck = 4, Finished = 5 } // 获取最大 ID long maxID = Enum.GetValues(typeof(TestType)) .Cast<TestType>() .Max(value => (long)value); Console.WriteLine($"MaxID = {maxID}"); // 输出: MaxID = 5 ``` > ✅ 优势:代码简洁高效,适应所有底层类型(int/long 等)[^3] #### 2. 循环遍历法 ```csharp long maxValue = long.MinValue; foreach (TestType value in Enum.GetValues(typeof(TestType))) { long currentValue = Convert.ToInt64(value); if (currentValue > maxValue) maxValue = currentValue; } ``` #### 3. 泛型扩展方法(工程级方案) ```csharp public static class EnumExtensions { public static long GetMaxValue<T>() where T : Enum { return Enum.GetValues(typeof(T)) .Cast<T>() .Max(value => Convert.ToInt64(value)); } } // 使用示例 var maxID = EnumExtensions.GetMaxValue<TestType>(); ``` --- ### ⚠️ 关键注意事项 1. **混合类型枚举处理** 当枚举显式赋值隐式赋值混合时: ```csharp public enum MixedType { A = 10, // 显式赋值 B, // 隐式赋值 B=11 C = 5 // 显式赋值 } // MaxID = 11(实际最大值) ``` 2. **负值场景** ```csharp public enum NegativeValues { Error = -1, Pending = 0, Success = 1 } // MaxID = 1 ``` 3. **标志枚举([Flags])的特殊性** ```csharp [Flags] public enum Permissions { None = 0, Read = 1, Write = 2, Execute = 4 } // MaxID = 4(非位或值 7) ``` 4. **空枚举处理** ```csharp if (!Enum.GetValues(typeof(MyEnum)).Any()) { throw new InvalidOperationException("空枚举类型"); } ``` --- ### 数学原理 设枚举有 $n$ 个成员,其值构成集合: $$S = \{ v_0, v_1, \dots, v_{n-1} \}$$ 则: $$\text{MaxID} = \max(S) = \max_{k \in [0, n-1]} v_k$$ --- ### 应用场景 1. **数据库字段定义**:根据 MaxID 选择匹配的整数类型 2. **序列化验证**:检测传入值是否在枚举范围内 ```csharp bool IsValid(int value) => value >= 0 && value <= GetMaxValue<MyEnum>(); ``` 3. **位标志校验**:验证组合值是否有效 ```csharp bool IsValidFlags(FlagsEnum flags) => (Convert.ToInt64(flags) & ~GetMaxValue<FlagsEnum>()) == 0; ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值