Marshal.SizeOf 和 C# 中 boolean 和 char 数据类型的 sizeof 运算符的相反行为
Opposite behavior of Marshal.SizeOf and sizeof operator for boolean and char data types in C#
我在 C# 中比较 Marshal.SizeOf
API 和 sizeof
运算符。他们对 char 和 bool 数据类型的输出不足为奇。以下是结果:
对于布尔值:
Marshal.SizeOf = 4
大小= 1
对于字符:
Marshal.SizeOf = 1
sizeof = 2
在 this link 从 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.
我不太了解封送处理的技术细节,但它与 运行-time heuristics 有关,当事情发生变化时。按照 bool 的逻辑,大小从 1 变为 4。但是对于 char(从 2 到 1),它正好相反,这对我来说是一个飞旋镖。我认为对于 char 也应该增加 bool 的发生方式。有人可以帮助我理解这些相互矛盾的行为吗?
抱歉,您确实 必须考虑技术细节才能理解这些选择。 pinvoke 的目标语言是 C 语言,这是一种以现代标准衡量的非常古老的语言,具有 lot 的历史,并在 lot 的不同机器中使用架构。它对类型的大小做出很少的假设,byte 的概念不存在。这使得该语言非常容易移植到 C 发明时常见的机器类型以及超级计算机和数字信号处理器中使用的不寻常架构。
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_t
和 char32_t
。然而,在以 Windows 为目标的编译器中,它始终是 16 位,因为这是操作系统对字符的选择(又名 WCHAR)。它不是各种 Unix 风格,他们喜欢 utf8。
这在 C# 中也很有效,您不会受限于 1 字节字符。 .NET 框架中的每个类型都有一个带有 CharSet 属性 的隐式 [StructLayout] 属性。默认为CharSet.Ansi
,匹配C语言默认。但是,您可以轻松地应用自己的并选择 CharSet.Unicode。现在每个字符有两个字节,使用 utf16 编码,字符串按原样复制,因为 .NET 也使用 utf16。然而,确保本机代码期望该编码中的字符串取决于您。
我在 C# 中比较 Marshal.SizeOf
API 和 sizeof
运算符。他们对 char 和 bool 数据类型的输出不足为奇。以下是结果:
对于布尔值:
Marshal.SizeOf = 4
大小= 1
对于字符:
Marshal.SizeOf = 1
sizeof = 2
在 this link 从 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.
我不太了解封送处理的技术细节,但它与 运行-time heuristics 有关,当事情发生变化时。按照 bool 的逻辑,大小从 1 变为 4。但是对于 char(从 2 到 1),它正好相反,这对我来说是一个飞旋镖。我认为对于 char 也应该增加 bool 的发生方式。有人可以帮助我理解这些相互矛盾的行为吗?
抱歉,您确实 必须考虑技术细节才能理解这些选择。 pinvoke 的目标语言是 C 语言,这是一种以现代标准衡量的非常古老的语言,具有 lot 的历史,并在 lot 的不同机器中使用架构。它对类型的大小做出很少的假设,byte 的概念不存在。这使得该语言非常容易移植到 C 发明时常见的机器类型以及超级计算机和数字信号处理器中使用的不寻常架构。
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_t
和 char32_t
。然而,在以 Windows 为目标的编译器中,它始终是 16 位,因为这是操作系统对字符的选择(又名 WCHAR)。它不是各种 Unix 风格,他们喜欢 utf8。
这在 C# 中也很有效,您不会受限于 1 字节字符。 .NET 框架中的每个类型都有一个带有 CharSet 属性 的隐式 [StructLayout] 属性。默认为CharSet.Ansi
,匹配C语言默认。但是,您可以轻松地应用自己的并选择 CharSet.Unicode。现在每个字符有两个字节,使用 utf16 编码,字符串按原样复制,因为 .NET 也使用 utf16。然而,确保本机代码期望该编码中的字符串取决于您。