c# - C# 中 boolean 和 char 数据类型的 Marshal.SizeOf 和 sizeof 运算符的相反行为

标签 c# marshalling sizeof

我正在比较 Marshal.SizeOf API 与 C# 中的 sizeof 运算符。他们对 char 和 bool 数据类型的输出不足为奇。以下是结果:

对于 bool 值:

编码(marshal).SizeOf = 4

大小= 1

对于字符:

编码(marshal).SizeOf = 1

大小= 2

关于 this来自 MSDN 的链接我得到以下文本:

For all other types, including structs, the sizeof operator can be used only in unsafe code blocks. Although you can use the Marshal.SizeOf method, the value returned by this method is not always the same as the value returned by sizeof. Marshal.SizeOf returns the size after the type has been marshaled, whereas sizeof returns the size as it has been allocated by the common language runtime, including any padding.

我不太了解编码(marshal)处理的技术细节,但它与事情发生变化时的运行时启发式方法有关。按照 bool 的逻辑,大小从 1 变为 4。但是对于 char(从 2 到 1),它正好相反,这对我来说是一个飞旋镖。我认为对于 char 也应该增加 bool 的发生方式。有人可以帮助我理解这些相互矛盾的行为吗?

最佳答案

抱歉,您确实确实必须考虑技术细节才能理解这些选择。 pinvoke 的目标语言是 C 语言,这是一种以现代标准衡量的非常古老的语言,具有很多的历史,并用于很多不同的机器架构。它对类型的大小做出很少的假设,字节 的概念不存在。这使得该语言非常容易移植到 C 发明时常见的机器类型以及 super 计算机和数字信号处理器中使用的不寻常架构。

C 最初没有 bool 类型。逻辑表达式改为使用 int,其中 0 值表示 false,任何其他值表示 true。也继承到 winapi 中,它确实使用了 BOOL 类型,它是 int 的别名。所以 4 是合乎逻辑的选择。但这不是一个普遍的选择,您必须注意,许多 C++ 实现使用单个字节,COM 自动化选择两个字节。

C 确实有一个 char 类型,唯一的保证是它至少有 8 位。它是有符号的还是无符号的是未指定的,今天的大多数实现都使用有符号的。对 8 位字节的支持如今在可以执行托管代码的那种体系结构上是普遍的,因此 char 在实践中始终是 8 位。所以 1 是合乎逻辑的选择。

这不会让你开心,没有人会对此感到高兴,你不能支持用任意语言编写的 8 位字符类型的文本。 Unicode 的出现是为了解决许多可能使用的 8 位编码的灾难,但它对 C 和 C++ 语言没有太大影响。他们的委员会确实将 wchar_t(宽字符)添加到标准中,但为了与旧做法保持一致,他们没有确定其大小。这使它变得毫无用处,迫使 C++ 稍后添加 char16_tchar32_t。然而,在针对 Windows 的编译器中它总是 16 位,因为这是操作系统对字符的选择(又名 WCHAR)。它不是各种 Unix 风格,他们喜欢 utf8。

这在 C# 中也很有效,您不会被 1 字节的字符所困。 .NET 框架中的每个类型都有一个带有 CharSet 属性的隐式 [StructLayout] 属性。默认为CharSet.Ansi,匹配C语言默认。但是,您可以轻松地应用自己的并选择 CharSet.Unicode。现在每个字符有两个字节,使用 utf16 编码,字符串按原样复制,因为 .NET 也使用 utf16。然而,确保 native 代码期望该编码中的字符串取决于您。

关于c# - C# 中 boolean 和 char 数据类型的 Marshal.SizeOf 和 sizeof 运算符的相反行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38969438/

相关文章:

c - 为什么 sizeof(!5.6) 给出输出 2?

c# - 如何在 C# 中更改 PriorityQueue 中包含的元素的优先级

c# - 使用从 C# 到非托管驱动程序的嵌入式指针编码结构

c++ - 为什么标准本身没有将 sizeof(bool) 定义为 1?

delphi - 简单编码解码对象

C# AppDomains 和线程

c++ - 有没有办法获取函数的大小并为其复制和执行分配内存?

c# - 同步 c#/asp.net 预订应用程序

c# - 使用 C# 进行电子邮件排队

c# - 仅接受自签名 SSL 证书 C#