我应该在与 C# 交互时使用固定大小的数据类型吗
Should I use fixed size data types while interfacing with C#
据我所知,C++ 标准不保证 int
等基本数据类型的大小。它只是保证表示 int
变量的最少位数。因此,从平台到平台,这可能会发生变化。
在使用包含托管部分和本机部分(C++ 和 C#)的应用程序以及普通 C 风格界面(Pinvokes
和 Marshal
..)时,这种不一致的数据类型大小可能会导致乱七八糟。
那么,在界面中始终使用固定大小的数据类型好吗?它有什么缺点吗?
由于 C# int
始终是 32 位的,您必须确保您的 C++ 部分在连接时也使用 32 位整数。缺点不应该让你担心,因为这是必须的。
另外,不清楚 64 位整数对您来说是好是坏。这取决于你在做什么。他们会拿走更多 space,那是肯定的。
您可以定义自己的数据类型,无论您使用何种架构,其大小都不会改变。优点是当你移动到不同的架构(例如 32 到 64 位等)时,你不需要修改你的程序。缺点是,假设您最初是为 32 位编写程序并考虑以下内容,并且您已经定义了这样的 64 位数据类型。
typedef struct A
{
int a;
int b;
} my64bitint;
要使用它,您需要编写自己的代码。当你移动到 64 位时,你可以继续使用相同的,但是你将无法获得你在新 arch 中获得的 64 位整数的优势。您需要更改代码以使用 64 位整数。
对于整数类型:是的,你应该。
在 C# 端更容易,因为所有整数类型都有固定大小,不依赖于平台位数。
在 C++ 端,您可以使用以下相应类型:
int8_t
-> sbyte
= System.SByte
,这不是 ECMA 标准,但在 :NET 和 Mono
中可用
uint8_t
->byte
=System.Byte
int16_t
-> short
= System.Int16
uint16_t
->ushort
=System.UInt16
int32_t
-> int
= System.Int32
uint32_t
->uint
=System.UInt32
int64_t
-> long
= System.Int64
uint64_t
->ulong
=System.UInt64
交换指针类型也是安全的。尽管它们的大小可能会有所不同,但对于特定进程的调用方和被调用方大小始终相同。
即:如果进程是 64 位的,则您的 C++ 代码必须已编译为 64 位,因此它的指针具有 64 位。此过程将使用 64 位 .NET 运行时,因此 .NET 中的指针也将是 64 位。
(顺便说一句:C# 中的指针类型是 System.IntPtr
和 ... *
)。
对于浮点类型来说有点难。 C++ 标准没有给你任何提示 float
或 double
是如何存储的。不是尺寸也不是技术。
实际上,我所知道的所有 C/C++ 编译器(MSVC、gcc/g++、clang/clang++)在我使用过的所有平台上(Windows、MinGW、 Linux) 以 32 位 IEEE-754 格式存储 float
,以 64 位 IEEE-754 格式存储 double
。
我不知道 .NET 是否定义了固定格式,但根据我的经验,.NET 和 Mono 以相同的方式进行(float
= System.Single
是 32 位 IEEE-754 和 double
= System.Double
是 64 位 IEEE-754).
因此您可以决定是否相信我对 C++ 方面的观察...
据我所知,C++ 标准不保证 int
等基本数据类型的大小。它只是保证表示 int
变量的最少位数。因此,从平台到平台,这可能会发生变化。
在使用包含托管部分和本机部分(C++ 和 C#)的应用程序以及普通 C 风格界面(Pinvokes
和 Marshal
..)时,这种不一致的数据类型大小可能会导致乱七八糟。
那么,在界面中始终使用固定大小的数据类型好吗?它有什么缺点吗?
由于 C# int
始终是 32 位的,您必须确保您的 C++ 部分在连接时也使用 32 位整数。缺点不应该让你担心,因为这是必须的。
另外,不清楚 64 位整数对您来说是好是坏。这取决于你在做什么。他们会拿走更多 space,那是肯定的。
您可以定义自己的数据类型,无论您使用何种架构,其大小都不会改变。优点是当你移动到不同的架构(例如 32 到 64 位等)时,你不需要修改你的程序。缺点是,假设您最初是为 32 位编写程序并考虑以下内容,并且您已经定义了这样的 64 位数据类型。
typedef struct A
{
int a;
int b;
} my64bitint;
要使用它,您需要编写自己的代码。当你移动到 64 位时,你可以继续使用相同的,但是你将无法获得你在新 arch 中获得的 64 位整数的优势。您需要更改代码以使用 64 位整数。
对于整数类型:是的,你应该。
在 C# 端更容易,因为所有整数类型都有固定大小,不依赖于平台位数。
在 C++ 端,您可以使用以下相应类型:
int8_t
-> sbyte
= System.SByte
,这不是 ECMA 标准,但在 :NET 和 Mono
uint8_t
->byte
=System.Byte
int16_t
-> short
= System.Int16
uint16_t
->ushort
=System.UInt16
int32_t
-> int
= System.Int32
uint32_t
->uint
=System.UInt32
int64_t
-> long
= System.Int64
uint64_t
->ulong
=System.UInt64
交换指针类型也是安全的。尽管它们的大小可能会有所不同,但对于特定进程的调用方和被调用方大小始终相同。
即:如果进程是 64 位的,则您的 C++ 代码必须已编译为 64 位,因此它的指针具有 64 位。此过程将使用 64 位 .NET 运行时,因此 .NET 中的指针也将是 64 位。
(顺便说一句:C# 中的指针类型是 System.IntPtr
和 ... *
)。
对于浮点类型来说有点难。 C++ 标准没有给你任何提示 float
或 double
是如何存储的。不是尺寸也不是技术。
实际上,我所知道的所有 C/C++ 编译器(MSVC、gcc/g++、clang/clang++)在我使用过的所有平台上(Windows、MinGW、 Linux) 以 32 位 IEEE-754 格式存储 float
,以 64 位 IEEE-754 格式存储 double
。
我不知道 .NET 是否定义了固定格式,但根据我的经验,.NET 和 Mono 以相同的方式进行(float
= System.Single
是 32 位 IEEE-754 和 double
= System.Double
是 64 位 IEEE-754).
因此您可以决定是否相信我对 C++ 方面的观察...