2012-07-08 1 views
33

sizeof와 alignof의 차이점은 무엇입니까?sizeof와 alignof의 차이점은 무엇입니까?

#include <iostream> 

#define SIZEOF_ALIGNOF(T) std::cout<< sizeof(T) << '/' << alignof(T) << std::endl 

int main(int, char**) 
{ 
     SIZEOF_ALIGNOF(unsigned char); 
     SIZEOF_ALIGNOF(char); 
     SIZEOF_ALIGNOF(unsigned short int); 
     SIZEOF_ALIGNOF(short int); 
     SIZEOF_ALIGNOF(unsigned int); 
     SIZEOF_ALIGNOF(int); 
     SIZEOF_ALIGNOF(float); 
     SIZEOF_ALIGNOF(unsigned long int); 
     SIZEOF_ALIGNOF(long int); 
     SIZEOF_ALIGNOF(unsigned long long int); 
     SIZEOF_ALIGNOF(long long int); 
     SIZEOF_ALIGNOF(double); 
} 

가 출력

1/1 1/1 2/2 2/2 4/4 4/4 4/4 4/4 4/4 8/8 8/8 8/8

나는 정렬이 무엇인지 모르겠다 ...?

+16

네이티브 형식 대신 struct를 사용하여 다시 시도하십시오. –

+1

'지정된 유형의 인스턴스에 필요한 정렬 (바이트 단위의 정수 (2의 제곱))을 반환합니다. '- http://en.cppreference.com/w/cpp/language/alignof. 'sizeof'는 크기를 바이트 단위로 제공합니다. – chris

+1

아마도 언급 할만한 가치가 있습니다 - [sizeof는 항상 alignof의 배수입니다] (http://stackoverflow.com/questions/4637774/is-the-size-of-a-struct-required-to-be-an-exact-multiple -of-the-alignment-of-tha) – Steve314

답변

3

sizeof operator은 유형의 실제 유형 또는 인스턴스의 크기 (바이트)를 제공합니다.

alignof operator은 지정된 유형의 인스턴스에 필요한 바이트 정렬을 제공합니다.

+6

"정렬"이란 무엇입니까? – user1494506

14

두 연산자는 근본적으로 다른 것들을 수행합니다. sizeof은 타입의 크기 (얼마나 많은 메모리가 필요한가) 인 반면 alignof은 얼마나 많은 바이트가 정렬되어야 하는지를 알려줍니다. 테스트 한 프리미티브에 크기와 동일한 정렬 요구 사항이 적용됩니다 (생각할 경우 의미가 있습니다).

struct Foo { 
    int a; 
    float b; 
    char c; 
}; 

alignof(Foo) 4.

+1

왜? 'alignof'는 무엇입니까? – user1494506

+1

@tskuzzy 당신은'alignof (Foo)'가 4를 반환 할 것이라고 말했습니다. 그러나 그것은 목표 ABI에 달려 있습니다. 이것은 ia32 (x86)에서는 가능하지만 ARM, MIPS, PowerPC에서는 그렇지 않습니다. – ydroneaud

+3

4 ??? 나는 정말로 이해하지 못한다 – Offirmo

54

음, "메모리"기본적으로 바이트의 거대한 배열 반환합니다

는 대신 구조체가있는 경우 어떻게되는지 생각해보십시오. 그러나 정수와 같은 대부분의 경우 정수를 저장하는 데 1 바이트 이상이 필요합니다. 예를 들어 32 비트 값은 4 바이트의 연속 메모리를 사용합니다.

이제 컴퓨터의 메모리 모듈은 일반적으로 "바이트"가 아닙니다. 그들은 또한 4 바이트 블록처럼 "병렬로"몇 바이트로 구성됩니다. 이것은 "정렬"라는 것입니다

memory byte 0 1 2 3  4 5 6 7  8 9 10 11 
integer  goooood 
        baaaaaaaaad 

: CPU 프로세서

, 그것은 더 효율적으로 더 쉽게 = "십자가"등의 블록 경계는 정수처럼 뭔가를 읽고하지 않을 경우에 더 나은 성능의 정렬 4는이 유형의 데이터가 4의 배수 인 주소에서 시작하여 저장되어야 함을 의미합니다.

sizeof == alignof가 올바르지 않습니다. 구조를 시도하십시오. 구조체도 정렬됩니다 (개별 멤버가 올바른 주소로 끝나야하기 때문에).하지만 크기가 훨씬 커집니다.

+14

추가 포인트 - x86은 정렬되지 않은 읽기 및 쓰기 (대부분 천천히하지만 올바르게)를 수행하지만 일부 아키텍처에서는 모든 작업이 정렬되어야하며 x86에서도 정렬되어야하는 특별한 경우가있다 (SIMD 지시, 나는 생각한다). – Steve314

+0

감사합니다! 이제 알겠습니다. – user1494506

+2

@ user1494506 -이 질문이나 다른 대답이 질문에 올바르게 대답하면 * 표시가 올바른지 생각해보십시오. (물론 이것은 * 순전히 선택 사항입니다.) 사람들이 그렇게 말하기 때문에 (예를 들어 지금 말하고있는 것처럼) 답변을 수락하지 마십시오. :) – ArjunShankar

5

alignof 값은 기본 유형의 sizeof 값과 같습니다.

차이점은 사용 된 정의 된 데이터 형식 (예 : struct; 예를 들어

typedef struct { int a; double b; } S; 
//cout<<alignof(s);        outputp: 8; 
//cout<<sizeof(S);        output: 12; 

따라서 sizeof 값은 주어진 데이터 형식에 필요한 총 크기입니다. 이며 alignof 값은 구조에서 가장 큰 요소의 정렬 요구 사항입니다.

alignof : 특정 정렬 경계에 메모리를 할당합니다.

6

이전 질문 (대답은 ...이라고 표시되지 않았지만)이 예제가 Christian Stieber의 답변 외에 약간의 차이를 더 잘 나타내 었다고 생각했습니다. sizeof 연산자는 (S) 출력이 16하지 (12)

// c has to occupy 8 bytes so that d (whose size is 8) starts on a 8 bytes boundary 
//   | 8 bytes | | 8 bytes | | 8 bytes | 
struct Bad { char c;  double d;  int i;  }; 
cout << alignof(Bad) << " " << sizeof(Bad) << endl; // 8 24 

//    | 8 bytes | | 8 bytes |  
struct Good { double d;  int i; char c;   }; 
cout << alignof(Good) << " " << sizeof(Good) << endl; // 8 16 

그대로 또한 Meluha의 대답은 그것은 또한 규모에 의해 최고의 주문 회원임을 증명에 오류가 가장 큰, (이 경우 더블) 첫번째 회원이 다른 사람으로 그 회원에 의해 제약받습니다.

2

제공된 답변에 대해서는 맞춤이 실제로 무엇인지 혼란스러워 보입니다. 두 종류의 정렬이 있기 때문에 혼동이 발생할 수 있습니다.

1

이 인스턴스가 회원 구조/클래스 유형 내 의 특정 주문에 대한 바이트 수에 얼마나 큰 밖으로 주문 질적 측정 회원 정렬. 일반적으로 컴파일러는 멤버가 구조 내에서 내림차순 (즉, 가장 큰 멤버, 가장 작은 멤버가 마지막)으로 정렬되는 경우 구조/클래스 인스턴스를 압축 할 수 있습니다. 다음을 고려하십시오.

struct A 
{ 
    char c; float f; short s; 
}; 

struct B 
{ 
    float f; short s; char c; 
}; 

두 구조는 완전히 동일한 정보를 포함합니다. 이 예를 위해서; float 유형은 4 바이트, 짧은 유형은 2, 문자는 1 바이트를 사용합니다. 그러나 첫 번째 구조 A는 임의의 순서로 멤버가 있고 두 번째 구조 B는 멤버의 바이트 크기에 따라 순서가 지정됩니다 (특정 아키텍처에서는 다를 수 있음).이 예제에서 4 바이트 정렬을 사용하는 x86 Intel CPU 아키텍처를 가정합니다. 당신은 크기가 7 바이트로 기대하는 경우, 회원이 는 1 바이트 정렬을 사용하여 구조로 포장 된 것을 가정 할 것이다

printf("size of A: %d", sizeof (A)); // size of A: 12; 
printf("size of B: %d", sizeof (B)); // size of B: 8; 

: 이제 구조의 크기를 고려하십시오. 일부 컴파일러는 이것을 허용하지만 일반적으로 대부분의 컴파일러는 역사적인 이유로 (대부분의 CPU가 DWORD (더블 워드) 또는 QWORD (쿼드 워드) 범용 레지스터로 작업) 때문에 4 바이트 또는 8 바이트 정렬을 사용합니다.

패킹을 달성하기 위해 작업시 2 개의 패딩 메커니즘이 있습니다.

  1. 먼저 얻어진 바이트 크기를 바이트 - 정렬보다 작거나 같으면 다음 부재 (들) "병합"되는 바이트 - 정렬보다 바이트 크기 작은있는 각 부재. 구조체 B에서 멤버 s와 c는이 방식으로 병합 될 수 있습니다. 이들의 결합 된 크기는 c == 3 바이트 인 경우 s + 1 바이트의 경우 2 바이트입니다. < = 4 바이트 정렬 인 경우. 구조체 A의 경우 이러한 병합이 발생할 수 없으며 구조체의 패킹에서 각 멤버가 효과적으로 4 바이트를 소비합니다.

  2. 다음 구조가 정렬 경계에서 시작할 수 있도록 구조의 전체 크기가 다시 채워집니다. 예제 B에서 전체 바이트 수는 7이됩니다. 다음 4 바이트 경계는 바이트 8에 있으므로 구조에 1 바이트가 채워져 배열 할당이 긴밀한 인스턴스 순서로 허용됩니다.

Visual C++/GCC에서는 1 바이트, 2 및 2 배 이상의 배수가 서로 다른 정렬을 허용합니다.이것은 당신의 컴파일러가 당신의 아키텍처에 맞는 최적의 코드를 생성하는 능력에 반하는 것이라는 것을 이해하십시오. 실제로 다음 예제에서 각 바이트는 각 읽기 작업에 대해 싱글 바이트 명령어를 사용하여 단일 바이트로 읽습니다. 실제로 하드웨어는 캐시로 읽는 각 바이트를 포함하는 전체 메모리 라인을 가져오고 4 바이트가 동일한 DWORD에 있고 CPU 레지스터에 1 명령으로로드 될 수 있더라도 4 번 명령을 실행합니다.

이 밀접 2 심기구에 관한 것이다

할당 정렬 앞에서 설명한

#pragma pack(push,1) 
struct Bad 
{ 
    char a,b,c,d; 
}; 
#pragma pack(pop) 

2. 그러나, llocation 정렬의 malloc/memalloc 변형에 지정 될 수있다 할당 기능. 따라서 구조체/객체 유형의 바이트 정렬이 제안하는 것보다 다른 (일반적으로 2보다 큰 배수) 정렬 경계에서 객체를 할당하는 것이 가능합니다.

size_t blockAlignment = 4*1024; // 4K page block alignment 
void* block = malloc(sizeof(T) * count, blockAlignment); 

코드는 다시 4096

이러한 할당 정렬을 사용하는 이유의 배수로 도착지 순전히 아키텍처 타입 T의 카운트 인스턴스의 블록을 배치되는 것이다. 예를 들어 페이지 정렬 주소에서 블록을 읽고 쓰는 것이 더 빠릅니다. 주소 범위가 캐시 계층에 적합하기 때문입니다. 다른 '페이지'로 분할되는 범위는 페이지 경계를 넘을 때 캐시를 휴지통으로 만듭니다. 서로 다른 미디어 (버스 아키텍처)는 서로 다른 액세스 패턴을 가지며 서로 다른 정렬을 통해 이점을 얻을 수 있습니다. 일반적으로 4, 16, 32 및 64 K 페이지 크기의 정렬은 일반적이지 않습니다.