gpt4 book ai didi

c# - Int16 - .net 中的字节容量?

转载 作者:太空狗 更新时间:2023-10-29 20:58:53 29 4
gpt4 key购买 nike

为什么:

short a=0;
Console.Write(Marshal.SizeOf(a));

显示 2

但是如果我看到 IL 代码,我会看到:

/*1*/   IL_0000:  ldc.i4.0    
/*2*/ IL_0001: stloc.0
/*3*/ IL_0002: ldloc.0
/*4*/ IL_0003: box System.Int16
/*5*/ IL_0008: call System.Runtime.InteropServices.Marshal.SizeOf
/*6*/ IL_000D: call System.Console.Write

第 1 行的 LDC 表示:

Push 0 onto the stack as int32.

所以肯定有4个字节被占用。

但是 sizeOf 显示 2 字节...

我在这里错过了什么? short实际在mem中占用多少字节?

我听说过有一个填充到 4 个字节的情况,这样处理起来会更快。这里也是这样吗?

(请忽略 syncRoot 和 GC 根标志字节,我只是问 2 vs 4)

最佳答案

CLI 规范对于允许在堆栈上的数据类型非常明确。短 16 位整数不是其中之一,因此此类整数在加载到堆栈时会转换为 32 位整数(4 个字节)。

第 III.1.1 部分包含所有详细信息:

1.1 Data types

While the CTS defines a rich type system and the CLS specifies a subset that can be used for language interoperability, the CLI itself deals with a much simpler set of types. These types include user-defined value types and a subset of the built-in types. The subset, collectively called the "basic CLI types", contains the following types:

  • A subset of the full numeric types (int32, int64, native int, and F).
  • Object references (O) without distinction between the type of object referenced.
  • Pointer types (native unsigned int and &) without distinction as to the type pointed to.

Note that object references and pointer types can be assigned the value null. This is defined throughout the CLI to be zero (a bit pattern of all-bits-zero).

1.1.1 Numeric data types

  • The CLI only operates on the numeric types int32 (4-byte signed integers), int64 (8-byte signed integers), native int (native-size integers), and F (native-size floating-point numbers). However, the CIL instruction set allows additional data types to be implemented:

  • Short integers: The evaluation stack only holds 4- or 8-byte integers, but other locations (arguments, local variables, statics, array elements, fields) can hold 1- or 2-byte integers. For the purpose of stack operations the bool and char types are treated as unsigned 1-byte and 2-byte integers respectively. Loading from these locations onto the stack converts them to 4-byte values by:

    • zero-extending for types unsigned int8, unsigned int16, bool and char;
    • sign-extending for types int8 and int16;
    • zero-extends for unsigned indirect and element loads (ldind.u*, ldelem.u*, etc.);; and
    • sign-extends for signed indirect and element loads (ldind.i*, ldelem.i*, etc.)

Storing to integers, booleans, and characters (stloc, stfld, stind.i1, stelem.i2, etc.) truncates. Use the conv.ovf.* instructions to detect when this truncation results in a value that doesn't correctly represent the original value.

[Note: Short (i.e., 1- and 2-byte) integers are loaded as 4-byte numbers on all architectures and these 4-byte numbers are always tracked as distinct from 8-byte numbers. This helps portability of code by ensuring that the default arithmetic behavior (i.e., when no conv or conv.ovf instruction is executed) will have identical results on all implementations.]

Convert instructions that yield short integer values actually leave an int32 (32-bit) value on the stack, but it is guaranteed that only the low bits have meaning (i.e., the more significant bits are all zero for the unsigned conversions or a sign extension for the signed conversions). To correctly simulate the full set of short integer operations a conversion to a short integer is required before the div, rem, shr, comparison and conditional branch instructions.

……等等。

推测地说,做出此决定可能是为了简化架构或为了速度(或可能两者兼而有之)。现代 32 位和 64 位处理器使用 32 位整数比使用 16 位整数更有效,并且由于所有可以用 2 字节表示的整数也可以用 4 字节表示,所以这种行为是合理的.

唯一使用 2 字节整数而不是 4 字节整数真正有意义的情况是,如果您更关心内存使用而不是执行速度/效率。在那种情况下,您需要拥有一大堆这些值,可能打包到一个结构中。这就是您关心 Marshal.SizeOf 的结果的时候。

关于c# - Int16 - .net 中的字节容量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17511737/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com