通過查看available LDC instructions可以很容易地知道發生了什麼。注意可用的操作數類型的有限集合,有沒有版本可用,加載一個short類型的常量。只要int,long,float和double。這些限制在其他地方是可見的,例如Opcodes.Add指令同樣受到限制,不支持添加其中一個較小類型的變量。
IL指令集是非常有意地這樣設計的,它反映了一個簡單的32位處理器的功能。想到的處理器類型是RISC類型,他們在九十歲時有他們的乾草日。大量的32位cpu寄存器只能處理32位整數和IEEE-754浮點類型。英特爾x86內核不是一個很好的例子,雖然很常用,但它是一種CISC設計,實際上支持在8位和16位操作數上加載和執行算術運算。但這更像是一次歷史性的事故,它使機器翻譯程序變得簡單,從8位8080和16位8086處理器開始。但是這種能力並不是免費的,操縱16位值實際上會花費額外的CPU週期。
使IL與32位處理器功能良好匹配顯然使得實現抖動的人的工作更加簡單。存儲位置的大小可能仍然較小,但只有加載,存儲和轉換需要支持。只有在需要的時候,你的'a'變量是一個局部變量,無論如何它都佔用了堆棧幀或者cpu寄存器的32位。只有內存需要被截斷到正確的大小。
在代碼片段中沒有其他不明確的地方。因爲Marshal.SizeOf()需要參數類型爲的對象,所以需要將變量值加框。盒裝值通過類型句柄標識值的類型,它將指向System.Int16。 Marshal.SizeOf()具有知道它需要2個字節的內置知識。
這些限制確實反映了C#語言並導致不一致。這種編譯錯誤的永遠befuddles和惹惱C#程序員:
byte b1 = 127;
b1 += 1; // no error
b1 = b1 + 1; // error CS0266
哪家的IL限制,因此,不存在添加運算符以字節操作數。在這種情況下,需要將它們轉換爲下一個較大的兼容類型,即int。所以它適用於32位RISC處理器。現在有一個問題,32位的結果需要被重新轉換成一個只能存儲8位的變量。 C#語言在第一作業中使用錘子本身,但在第二作業中不合邏輯地需要使用錘子。
當你將它嵌入到一個更大的結構中時,例如在一個數組中,內存中的大小隻是一個有意義的概念。當你有一個局部變量時,它通常佔用一個完整的寄存器(AMD64上的64位),即使它只是一個字節。 C#編譯器在內部大多數情況下使用Int32,只要觀察到的行爲與Int16的行爲相匹配,它就在其權限內。 – CodesInChaos
@CodesInChaos所以它需要32位的4個字節?如果是這樣,爲什麼sieOf顯示2? –
大小是2,因爲它是這樣定義的,2個字節就足夠了。但是如果你有一個局部變量,它需要編譯器/ JITer需要的字節數。只要程序的行爲不受影響,他們就可以自由地做任何他們喜歡的事情。在方法運行期間,單個局部變量通常存儲在不同的地方。在你的情況下,他們甚至可能完全消除'a',而是簡單地使用常量'2'。 – CodesInChaos