2011-05-16 2 views
2

나는sizeof는 int 유형에서 어떻게 작동합니까?

(1)는 sizeof, (2) numeric_limits : 숫자, (3)과 노력 루프

의 결과를 확인하기 위해 모두 보고서를 비교하는 작은 프로그램을 모든 C++ 구현에서 "int 유형"의 크기와 관련하여 동일한 문제가 발생합니다. 그러나 sizeof 내부에 대해 알지 못하기 때문에 numeric_limits :: digits 만보고하는지 궁금합니다. 감사합니다

+0

많은 중복 사항 : 검색을 시도한 다음 묻는 결과를 찾지 못했지만 이전에 물어 본 결과와 "how sizeof work"가 몇 가지 결과를 산출한다는 간단한 검색이 있습니다. 나는 닫을 것을 표명하고있다. –

+0

[가능한 크기는 어떻게됩니까? 어떻게 내 자신을 쓸 수 있습니까?] (http://stackoverflow.com/questions/3094917/how-does-sizeof-work-how-can-i-write-my-own) –

답변

3

대부분의 컴파일러에서 sizeof() 일 가능성이 높습니다. 컴파일러가 주어진 유형 (또는 객체 유형) 그 내부 형식 테이블을 만들고 해당 형식의 정의 된 크기에 대한 리터럴을 생성 된 코드에 삽입합니다. 이것은 런타임이 아닌 컴파일 타임에 발생합니다.

주석에 대한 질문에 대답하기 위해 C++에서 컴파일러의 내부에 대한 언어 정의 액세스는 없습니다 (물론 sizeof() 자체는 제외). 필자가 아는 유일한 언어는 Ada이며, 컴파일러 독립적 인 코드 분석 도구를 작성하기 위해 ASIS을 제공합니다.

+0

내가 어떻게 할 수 있었는지 알게 되니? 수동으로 내부 형식 테이블의 값을 조회할까요? 감사. –

+1

@Chris : 'T'형식의 경우 'sizeof (T)'는 해당 데이터 비트를 생성합니다. 덜 구체적인 대답은 당신의 특정 컴파일러가 당신을 허용하지 않는 한 아닙니다. 그러면 결과는 당신이 설정하는 플래그에 따라 달라질 것입니다. –

+0

그래서 일반화하기 위해서는 컴파일 타임에 평가 된 테이블의 값 (심볼 테이블과 타입 테이블을 들었습니다)의 값입니다. –

1

sizeof 연산자는 컴파일러가 지정된 유형의 인스턴스가 메모리에서 차지할 크기 (바이트)를보고하는 컴파일 타임 구문입니다.

모든 컴파일러 구현에 따라 다르므로 일반적인 "this is sizeof works is"라는 대답은 어렵습니다. 일반에서는 형식의 모든 필드의 크기를 계산하고 정렬을 고려하면서 함께 추가합니다. 예를 들어

여기서 [1] (9)에 대향하는 많은 컴파일러 12 S2의 크기를보고

struct S1 { 
    int field1; 
    int field2; 
}; 

struct S2 { 
    int field1; 
    bool field2; 
    int field3; 
} 

sizeof(S1) == 8 
sizeof(S2) == 12; 

이유는이 정렬 문제를 고려하고, 따라서 3을 삽입해야한다는 출력 적당한 세트의 field2field3

[1] 사이의 갭을 보충하는 바이트 참고 : 나는 합당하지 않을 것이라고 말했습니다. :). C 컴파일러는 크기면에서 많은 유연성을 가지고 있으며 작업하는 컴파일러를 알지 못하면 크기에 대한 세부 사항을 기술하는 것이 거의 불가능합니다

0

sizeof에는 내부가 많지 않습니다. 피연산자 (표현식 또는 유형)의 크기를 바이트 단위로보고하는 내장 연산자입니다.

1 = sizeof(char) 
1 = sizeof(unsigned char) 
2 = sizeof(short) 
2 = sizeof(unsigned short) 
4 = sizeof(int) 
4 = sizeof(unsigned int) 
8 = sizeof(long) 
8 = sizeof(unsigned long) 
4 = sizeof(float) 
8 = sizeof(double) 
16 = sizeof(long double) 
8 = sizeof(size_t) 
8 = sizeof(ptrdiff_t) 
8 = sizeof(time_t) 
8 = sizeof(void *) 
8 = sizeof(char *) 
8 = sizeof(short *) 
8 = sizeof(int *) 
8 = sizeof(long *) 
8 = sizeof(float *) 
8 = sizeof(double *) 
8 = sizeof(int (*)(void)) 
8 = sizeof(double (*)(void)) 
8 = sizeof(char *(*)(void)) 
1 = sizeof(struct { char a; }) 
2 = sizeof(struct { short a; }) 
4 = sizeof(struct { int a; }) 
8 = sizeof(struct { long a; }) 
4 = sizeof(struct { float a; }) 
8 = sizeof(struct { double a; }) 
16 = sizeof(struct { char a; double b; }) 
16 = sizeof(struct { short a; double b; }) 
16 = sizeof(struct { long a; double b; }) 
4 = sizeof(struct { char a; char b; short c; }) 
16 = sizeof(struct { char a; char b; long c; }) 
4 = sizeof(struct { short a; short b; }) 
6 = sizeof(struct { char a[3]; char b[3]; }) 
8 = sizeof(struct { char a[3]; char b[3]; short c; }) 
16 = sizeof(struct { long double a; }) 
32 = sizeof(struct { char a; long double b; }) 

:

내가 같은 답변을 생산하는 이중 언어 프로그램 (C++의 C 하위 세트로 작성)를 가지고 ... 그리고 typeid를 사용하여 궁금 나를 잎 -

코드는 다소 복잡 (이것은 MacOS X 10.6.7의 G ++ 4.6.0 - 64 비트 컴파일로 제작되었습니다). 내가 __STDC_CONSTANT_MACROSTPRINT()SPRINT()와의 간섭이해야했다 이유를 정확히 기억하지 못하는

#ifdef __cplusplus 
#define __STDC_CONSTANT_MACROS 
#endif /* __cplusplus */ 

#include <stdio.h> 
#include <time.h> 
#include <stddef.h> 
#if __STDC_VERSION__ >= 199901L || HAVE_INTTYPES_H 
#include <inttypes.h> 
#endif /* __STDC_VERSION__ */ 

/* Using the simple C code in SPRINT() for structures leads to complaints from G++ */ 
/* Using the code in TPRINT() for pointers to functions leads to other complaints */ 
#define TPRINT(x) do { typedef x y; printf("%2u = sizeof(" #x ")\n", (unsigned int)sizeof(y)); } while (0) 
#define SPRINT(x) printf("%2u = sizeof(" #x ")\n", (unsigned int)sizeof(x)) 

int main(void) 
{ 
    /* Basic Types */ 
    SPRINT(char); 
    SPRINT(unsigned char); 
    SPRINT(short); 
    SPRINT(unsigned short); 
    SPRINT(int); 
    SPRINT(unsigned int); 
    SPRINT(long); 
    SPRINT(unsigned long); 

    SPRINT(float); 
    SPRINT(double); 
    SPRINT(long double); 
    SPRINT(size_t); 
    SPRINT(ptrdiff_t); 
    SPRINT(time_t); 

    /* Fancy integers */ 
#if __STDC_VERSION__ >= 199901L || HAVE_LONG_LONG 
    SPRINT(long long); 
    SPRINT(unsigned long long); 
#endif /* __STDC_VERSION__ || HAVE_LONG_LONG */ 
#if __STDC_VERSION__ >= 199901L || HAVE_INTTYPES_H 
    SPRINT(uintmax_t); 
#ifdef INT8_MAX 
    SPRINT(int8_t); 
#endif 
#ifdef INT16_MAX 
    SPRINT(int16_t); 
#endif 
#ifdef INT32_MAX 
    SPRINT(int32_t); 
#endif 
#ifdef INT64_MAX 
    SPRINT(int64_t); 
#endif 
#ifdef INT128_MAX 
    SPRINT(int128_t); 
#endif 
    SPRINT(int_least8_t); 
    SPRINT(int_least16_t); 
    SPRINT(int_least32_t); 
    SPRINT(int_least64_t); 
    SPRINT(int_fast8_t); 
    SPRINT(int_fast16_t); 
    SPRINT(int_fast32_t); 
    SPRINT(int_fast64_t); 
    SPRINT(uintptr_t); 
#endif /* __STDC_VERSION__ || HAVE_INTTYPES_H */ 

    /* Pointers */ 
    SPRINT(void *); 
    SPRINT(char *); 
    SPRINT(short *); 
    SPRINT(int *); 
    SPRINT(long *); 
    SPRINT(float *); 
    SPRINT(double *); 

    /* Pointers to functions */ 
    SPRINT(int (*)(void)); 
    SPRINT(double (*)(void)); 
    SPRINT(char *(*)(void)); 

    /* Structures */ 
    TPRINT(struct { char a; }); 
    TPRINT(struct { short a; }); 
    TPRINT(struct { int a; }); 
    TPRINT(struct { long a; }); 
    TPRINT(struct { float a; }); 
    TPRINT(struct { double a; }); 
    TPRINT(struct { char a; double b; }); 
    TPRINT(struct { short a; double b; }); 
    TPRINT(struct { long a; double b; }); 
    TPRINT(struct { char a; char b; short c; }); 
    TPRINT(struct { char a; char b; long c; }); 
    TPRINT(struct { short a; short b; }); 
    TPRINT(struct { char a[3]; char b[3]; }); 
    TPRINT(struct { char a[3]; char b[3]; short c; }); 
    TPRINT(struct { long double a; }); 
    TPRINT(struct { char a; long double b; }); 
#if __STDC_VERSION__ >= 199901L || HAVE_LONG_LONG 
    TPRINT(struct { char a; long long b; }); 
#endif /* __STDC_VERSION__ */ 
#if __STDC_VERSION__ >= 199901L || HAVE_INTTYPES_H 
    TPRINT(struct { char a; uintmax_t b; }); 
#endif /* __STDC_VERSION__ || HAVE_INTTYPES_H */ 

    return(0); 
} 

, 그러나 그것은을 만들기 위해 (다시 2010 월)에 필요한 있었는지 것 같았다 : 내가 사용하는 코드는 이중 언어 코드.

+0

그러나 이것은 64 비트 컴퓨터의 출력임을 유의해야합니다. 32 비트에서 long int는 8 비트 대신 4 바이트이고 long double은 32 비트 시스템에서만 12 바이트이고 포인터는 8 바이트 대신 4 바이트입니다. – DipSwitch

+0

@DipSwitch : 예, 64 비트 컴파일러입니다. 대답은 본질적으로 플랫폼에 따라 다릅니다. 예를 들어, Windows 64에서'sizeof (long) == 4'는 여전히 대부분의 유닉스 64 비트 컴퓨터에서'sizeof (long) == 8'입니다. 이것이 ILP32, LP64, ILP64, LLP64 시스템의 차이점입니다. –