2013-07-21 3 views
0

이름 공간과 구조체를 사용하려고 시도했습니다. &에 문제가 발생했습니다.컴파일러는 어떻게이 구조체에 메모리를 할당합니까?

C++ 

#include<iostream> 
using namespace std; 

namespace One 
{ 
    struct Data 
    { 
     int val; 
     char character; 
    }; 
} 

namespace Two 
{ 
    struct Data 
    { 
     int val; 
     bool boolean; 
    }; 
} 

void functionOne(void) 
{ 
    using namespace One; 
    cout << "functionOne()" << endl; 
    cout << "The size of struct Data : "; 
    cout << sizeof(Data) << endl; 
} 

void functionTwo(void) 
{ 
    using namespace Two; 
    cout << "functionTwo()" << endl; 
    cout << "The size of struct Data : "; 
    cout << sizeof(Data) << endl; 
} 

int main() 
{ 
    functionOne(); 
    functionTwo();  
} 

Output 
functionOne() 
The size of struct Data : 8 
functionTwo() 
The size of struct Data : 8 

동안 나는 다음에 '네임 스페이스의 두'의 코드를 변경할 때 :

namespace Two 
{ 
    struct Data 
    { 
     char val; 
     bool boolean; 
    }; 
} 

Output : 

functionOne() 
The size of struct Data : 8 
functionTwo() 
The size of struct Data : 2 

내가 컴파일러는 구조체에 메모리를 할당하는 방법을 알아낼 수 없습니다입니다. 미리 감사드립니다.

+0

@CarlNorum 링크의 대답은 32 비트 아키텍처에 대해 설명합니다. 정렬이 (일반적으로) 64 비트 아키텍처에서 수행되었음을 알 수 있습니까? –

+0

어떤 종류의 문제입니까? –

+0

@mozart, 아마도 귀하의 예와 같습니다. –

답변

5

여기의 문제는 정렬 요구 사항 때문일 가능성이 큽니다. 내가 틀리지 않았다면 구조체는 멤버의 가장 큰 정렬 요구 사항에 따라 정렬됩니다. 구조체의 첫 번째 버전에는 int; char;이 있습니다. 그것은 귀하의 컴퓨터에서 int는 4 바이트로 정렬되어 있으므로 컴파일러는 char 뒤에 여분의 3 바이트로 구조체를 채 웁니다. 두 번째 버전에서는 bool; char; 만 있고 크기는 1 바이트이며 컴퓨터에 잘 맞춰져 있으므로 컴파일러는 아무것도 채울 필요가 없으므로 크기가 2로 되돌아갑니다.

"컴퓨터에서"를 지정하는 이유는 여러 가지 요인에 따라 달라질 수 있기 때문입니다.

예쁜 그래프를 만들어 보겠습니다! 컴파일러는 메모리를 할당하는 방법에 대한

// One::Data (version 1) 
0    4    5    7 
[int (size 4), char (size 1), padding (size 3)][...] 
// Because of alignment restrictions on int, this needs a padding of 3 bytes 

// Two::Data (version 1) 
0    4    5    7 
[int (size 4), bool (size 1), padding (size 3)][...] 
// Because of alignment restrictions on int, this needs a padding of 3 bytes 

// One::Data (version 2), no change 

// Two::Data (version 2) 
0    1    2 
[char (size 1), bool (size 1)][...] 
// No alignment restrictions, therefore no padding is required 
+0

두 번째 네임 스페이스의 변경된 버전에 대해 왜 8 바이트를 할당합니까? 3 바이트가 패딩으로 사용됩니까? –

+0

@mozart 귀하의 질문을보고 있는데 변경된 버전의 크기가 2입니까? – Borgleader

+0

예. 크기가 2입니다. –

2

공식 답변은 는 "그러나 그것은에 원"입니다. 몇 가지 제한 사항이 있지만 수가 많지 않습니다. 그러나이 경우 상당히 많이 보입니다. 많은 유형에는 정렬 제한이 있고 (또는 가질 수도 있음) 값의 배수 인 주소에 배치해야합니다. 그리고 이러한 제한은 형식의 멤버가 포함 된 모든 클래스 까지 전파됩니다. 그렇지 않으면 이 클래스 멤버의 정렬을 따르지 않을 수 있기 때문입니다. 분명히, 당신의 컴퓨터에 는 bool (1의 크기가 있어야하며 char) (1)의 크기를 가지고 있으며, int 4의 크기를 가지고 있으며, 또한 One::Data에 따라서 4의 주소 여러에 정렬되어야하며, Two::Data, 당신은 패딩의 충분한 바이트 다음에 char 또는 bool, 뒤에 int이 구조 원칙 4. (의 배수의 전체 크기를 확인해야 char/bool과 패딩 수 어떤 순서로든 혼합 될 수 있지만, 실제로는 모든 컴파일러는 선언 후에 패딩을 넣습니다.)

어느 쪽도 bool도 아니고 char 어떤 정렬 제한이, 는 각 중 하나를 포함하는 클래스의 패딩 필요가 없기 때문에.

이것은 컴퓨터와 컴파일러에 따라 다릅니다. 일부 시스템 (예 : Sun Sparc 또는 IBM 메인 프레임)에서 값이 잘못 정렬되면 하드웨어 트랩이 발생하고 컴파일러는 으로 정렬 (및 패딩 삽입)이 거의 필요합니다.인텔에서는 다른 쪽 손에 잘못 정렬 된 액세스가 가능하지만 성능은 눈에 띄게 입니다. 컴파일러는 일반적으로 (그리고 Windows와 Linux 바이너리 API 모두 필요합니다)을 강제합니다. 그러나 컴파일러는 이것을 무시할 수 있으며 매우 초기의 인텔 컴파일러는 메모리가 보다 훨씬 더 빡빡 할 때 되돌아 왔습니다. (현대의 기계에서 의 성능이 가장 좋은 흥미로운 질문입니다. 어레이가 구조 중 하나와 함께있는 경우 으로 인한 메모리 부족으로 인한 메모리 부족 오류가 캐시에서 해결되거나 심지어 약간의 추가 비용으로 메모리 읽기 파이프 라인에서, 객체의 크기가 작 으면 캐시가 덜 흐트러 질 수 있으므로 misses가 발생하므로 성능이 향상됩니다. 그러나 아무런 조치도 취하지 않았습니다. 그래서 추측하고 있습니다.)

표준에서는 클래스 멤버가 순서대로 할당되어야한다는 점도 주목해야합니다. 기술적으로, 그 사이에 액세스 지정자가 없지만 실제로는 모든 컴파일러 이 항상 순서대로 할당합니다. 당신은 같은 클래스 그래서 만약 :

struct T 
{ 
    double d1; 
    double d2; 
    char c1; 
    char c2; 
}; 

이 위로 할 때 메모리 일 (24)의 크기를 갖게됩니다

struct T 
{ 
    double d1; 
    char c1; 
    double d2; 
    char c2; 
}; 

을은 (일반적으로)로 (32)의 크기를해야합니다 이 빡빡 했으므로 우리는 정기적으로 그러한 일에주의를 기울였습니다. 그러나 이제는 지역이 종종 문제가 될 수 있습니다. : : 다시 큰 숫자로 변수를 선언합니다. 가장 큰 것을 먼저 으로 지정하십시오.

관련 문제