2009-03-01 6 views
3

in .Net. 정수는 정수형이며 스택에 저장됩니다. 정수도 클래스입니다 (일반적으로 System.Int32). 그들은 CompareTo, Equals 등과 같은 메소드를 가지고 있습니다. 따라서 스택에서 4 바이트 이상을 가져야합니다. 그들이 정확히 4 바이트를 취할 것을 그러나 쇼 아래의 예 :.Net/C# : 정수의 실제 크기는 얼마입니까?

unsafe static void Main() 
{ 
    int a = 2, b = 4; 
    Console.WriteLine("Adress of a : {0}", (int)&a); 
    Console.WriteLine("Adress of b : {0}", (int)&b); 
    Console.WriteLine("Size of integer: {0}", (int)(&a) - (int)(&b)); 
} 

출력 :

Adress of a : 1372876 
Adress of b : 1372872 
Size of integer: 4 

는 CLR은 정수 및 기타 value 형 (에 대한 특별 대우을합니까 플로트, 긴 두 번 .. .)?

+1

int32는 구조가 아니라 클래스라고 생각합니다. – Shawn

+0

64 비트 OS에서 이것을 실행 해보십시오 ... –

+0

그렇다면 플랫폼은 int를 4 바이트로 유지합니다. * native int * 다른 문제입니다. 나쁜 예가 다른 값으로 끝날지 모르지만 – ShuggyCoUk

답변

5

따라서 스택에서 4 바이트를 초과해야합니다.

이것은 따르지 않습니다. 컴파일러 런타임은 정확한 유형을 알고 있습니다. 값 유형을 더 이상 서브 타입화할 수 없으므로 "vtable"또는 기타 오브젝트 특정 동적 디스패치 메커니즘이 필요하지 않습니다.

힙에 넣기 위해 값 형식을 박스로 묶는 경우 일반 .NET 개체 헤더가 필요합니다.

15

아니요, 값 유형이라는 사실은 스택에 저장된다는 의미는 아닙니다. 그들은 그들이 wherever the variable lives에 저장되어 있음을 의미합니다.

하지만 이봐 요, 지역 변수 비즈니스로 롤업 해 봅시다. 캡처하지 않은 상태에서 은 스택에 있습니다. 그리고 그들은 4 바이트 걸립니다. 왜 그들은 더 많은 걸릴까요? 스택에 vtable이 필요하지 않습니다. 메타 데이터가 이미 유형을 지정했기 때문에 가상 메소드를 호출 할 때 모호한 점이 없습니다.

EDIT : Shawn의 의견에서 지적했듯이 더 명확하게), System.Int32은 구조체가 아니라 클래스입니다. 실제로 CLR은 int의 boxed 값을 처리하기 위해 그림자 참조 형식을 만듭니다. 그러나 다른 문제입니다.

+0

Jon, 고마워요. 이제 머리 속의 일이 분명해집니다. –

+0

컴파일러가 메소드가 호출되는 변수의 유형을 알고 있고 그 메소드가 해당 클래스에 * 직접 정의되어 있으면 (가상의 경우 클래스/구조체에 대한 재정의가 있어야 함) 일리노이 주에서 필요한 모든 정보가 들어 있으므로 권투가 필요하지 않습니다 – ShuggyCoUk

4

값 유형은 메서드의 로컬 변수 인 경우 스택에 할당됩니다. 값 유형이 클래스의 구성원이면 힙의 오브젝트 메모리 영역의 일부로 할당됩니다.

값 유형 변수는 참조 유형처럼 유형을 추적하기 위해 추가 데이터가 필요하지 않습니다. 컴파일러는 값 유형 변수의 위치와 유형을 항상 알고 있으므로 실제 데이터 외에 추가 데이터가 필요하지 않습니다. Int32 변수는 항상 4 바이트입니다.

참조 유형은 힙에 할당되며 해당 참조 유형을 가리키는 참조 (또는 그 이상)가 있습니다. 참조 자체는 실제로 값 유형이므로 포인터 일 뿐이며 컴파일러는 포인터의 위치와 유형을 추적합니다. 참조의 유형은 가리키는 오브젝트의 유형과 동일 할 필요가 없으므로 오브젝트가 유형을 추적하기 위해 추가 정보를 필요로합니다. 예를 들어, 개체 참조 StringBuilder 클래스의 인스턴스를 가리키는 : 그것은 단지 (a 32에 4 바이트 포인터 것이다 그래서 여기

object o = new StringBuilder(); 

컴파일러 기준의 해당 유형의 추적은, 목적 bit 응용 프로그램). StringBuilder 객체는 힙에 저장되며 실제 유형을 추적하는 두 개의 추가 포인터가 있습니다.

값 유형도 상자로 묶을 수 있습니다. 즉힙에 객체로 저장됩니다. 이 값은 Object에 값 형식을 캐스팅 할 때 발생합니다.

object p = 42; 

이렇게하면 힙에 개체가 할당되고 정수 값이 복사됩니다. 이 객체는 유형을 추적하기 위해 여분의 유형 정보가 필요하므로 4 비트 대신 12 바이트를 사용합니다 (32 비트 응용 프로그램에서).

+0

StringBuilder 예를 들어, 두 개의 여분의 포인터가 참조 또는 개체의 일부입니까? 그리고 왜 둘뿐만 아니라 하나? 고맙습니다. –

+0

아니요, 8 바이트는 참조를 포함하지 않으며 힙에있는 객체의 일부입니다. 가상 메서드 테이블에 대한 포인터, 그리고 잘 설명되지 않은 네 바이트 더 ... 여기에 더 많은 정보가있다. http://stackoverflow.com/questions/489805/c-reference-variable-mem-allocation – Guffa

+0

그냥 "그것이 메소드의 지역 변수 인 경우"변수가 클로저에 캡처되지 않고 메소드가 반복자 블록이 아닌 경우 까다로운 경우 --p –

0
유형의 정의와 예를 들어, 해당 유형의 인스턴스에 저장된 값의 차이가있다

...

// type definition 
public class Bla {} 
// instance of type bla 
public Bla myBla = new Bla(); 

는 기본적으로 int 형의 크기는 것 같다 (4 바이트)하지만, 같은 알아 내면, 그것은 선언하는데 필요한 메모리 공간의 크기입니다.

타입 정의는 다른 곳에 저장됩니다. CompareTo와 같은 메소드는 선언 한 해당 유형의 인스턴스마다 단 한 번만 선언되며, 프레임 워크 라이브러리 자체의 일부로로드되기 때문에 이러한 정의는 효과적으로 0 공간을 차지합니다.