programing

C의 패딩 구조물

coolbiz 2023. 9. 7. 22:40
반응형

C의 패딩 구조물

인터뷰 질문입니다.지금까지는 그런 질문들이 순수하게 컴파일러에 의존하는 것이라 걱정할 필요가 없다고 생각했는데, 지금은 오히려 그것이 궁금합니다.

다음과 같은 두 가지 구조가 주어졌다고 가정합니다.

struct A {  
  int* a;  
  char b;  
 }  

그리고.

struct B {  
  char a;  
  int* b;  
}  

그래서 당신은 어떤 것을 선호하고 그 이유는 무엇입니까?컴파일러가 워드 크기(32비트 머신에서는 4바이트, 64비트 머신에서는 8바이트)의 일부 배수에서 구조를 위한 공간을 할당하므로 첫 번째 구조가 선호되어야 한다는 (어둠 속에서 다소 촬영하고 있었지만) 제 대답은 이렇게 되었습니다.따라서 컴파일러는 두 구조 모두에 대해 8바이트를 할당합니다(32비트 기계로 가정).그러나 첫 번째 경우 패딩은 내 변수(즉, a와 b 다음)가 모두 끝난 후에 이루어질 것입니다.그래서 혹시라도 b는 다음 패딩 바이트가 넘쳐서 파괴되는 값을 얻지만, 내 a는 여전히 안전합니다.

그는 별로 기뻐하지 않는 것 같았고 첫 번째 구조의 단점을 두 번째 구조보다 더 많이 요구했습니다.할 말이 별로 없었어요. :D

답변을 도와주시기 바랍니다.

저는 이 어떤 구조에도 이점이 없다고 생각합니다.이 방정식에는 하나의 상수가 있습니다.구조물의 구성원들의 순서는 선언대로 보장됩니다.

따라서 다음과 같은 경우 두 번째 구조는 크기가 더 작기 때문에 장점이 있을 수 있지만, 예제에서는 동일한 크기를 가질 수 없기 때문입니다.

struct {
    char a;
    int b;
    char c;
} X;

대.

struct {
    char a;
    char b;
    int c;
} Y;

아래 의견과 관련하여 조금 더 설명해 드리겠습니다.

아래의 모든 것은 100%는 아니지만 일반적으로 구조물이 32비트 시스템(int가 32비트인 경우)에서 구성되는 방식입니다.

구조 X:

|     |     |     |     |     |     |     |     |     |     |     |     |
 char  pad    pad   pad   ---------int---------- char   pad   pad   pad   = 12 bytes

구조:

|     |     |     |     |     |     |     |     |
 char  char  pad   pad   ---------int----------        = 8 bytes

일부 기계는 값이 일부 경계에 정렬될 때 더 효율적으로 데이터에 액세스합니다.데이터를 정렬해야 하는 경우도 있습니다.

SPARC나 Intel [34]86과 같은 최신 32비트 시스템이나 68020 이상의 Motorola 칩에서 각 데이터 항목은 일반적으로 유형 크기의 배수인 주소에서 시작하여 "자체 정렬"되어야 합니다.따라서 32비트 유형은 32비트 경계에서, 16비트 경계에서 16비트 유형은 16비트 경계에서 시작해야 합니다. 8비트 유형은 어디에서나 시작할 수 있습니다. 구조/배열/연합 유형은 가장 제한적인 멤버의 정렬을 가집니다.

그래서 당신은.

struct B {  
    char a;
    /* 3 bytes of padding ? More ? */
    int* b;
}

"자기 정렬" 경우에 패딩을 최소화하는 간단한 규칙은 (대부분의 경우에는 해가 되지 않음) 크기를 줄여서 구조 구성원을 주문하는 것입니다.

개인적으로 첫 번째 구조가 두 번째 구조와 비교했을 때 불리하지 않다고 봅니다.

이 특별한 경우에는 제1구조가 제2구조보다 불리하다고 생각할 수는 없지만, 최대 구성원을 우선시하는 일반적인 원칙에 불리한 경우를 생각해 볼 수 있습니다.

struct A {  
    int* a;
    short b;
    A(short num) : b(2*num+1), a(new int[b]) {} 
    // OOPS, `b` is used uninitialized, and a good compiler will warn. 
    // The only way to get `b` initialized before `a` is to declare 
    // it first in the class, or of course we could repeat `2*num+1`.
}

또한 큰 구조물의 경우 CPU가 작은 오프셋 값(예를 들어 최대 8비트 또는 즉시 값의 다른 제한)에 대해 포인터+오프셋에 액세스하기 위한 빠른 주소 지정 모드를 가지고 있다는 꽤 복잡한 경우에 대해서도 들었습니다.가장 일반적으로 사용되는 필드를 가장 빠른 명령 범위 내에 최대한 많이 넣음으로써 큰 구조물을 마이크로 최적화하는 것이 가장 좋습니다.

CPU는 포인터+오프셋과 포인터+4*오프셋을 위한 빠른 주소 지정 기능도 가지고 있을 수 있습니다.그렇다면 64개의 문자 필드와 64개의 int 필드가 있다고 가정합니다. 만약 당신이 문자 필드를 먼저 입력한다면 두 종류의 모든 필드는 최선의 명령을 사용하여 주소를 지정할 수 있는 반면, int 필드를 먼저 입력한다면 4 정렬되지 않은 문자 필드는 단지 다른 방식으로 접근해야 할 것입니다. 아마도 레지스터에 상수를 로드함으로써 말입니다.즉시 값을 사용할 수 있습니다. 왜냐하면 256바이트 제한을 벗어났기 때문입니다.

내가 직접 할 필요가 없었고, 예를 들어 x86의 경우 큰 즉각적인 값을 허용합니다.누구나 많은 시간을 집회를 응시하지 않는 한 보통 생각할 수 있는 최적화 방식이 아닙니다.

간단히 말해서, 일반적인 경우에는 어느 쪽도 선택하는 것이 유리하지 않습니다.실제로 선택이 중요한 유일한 상황은 구조물 패킹이 활성화된 경우입니다.struct A(두 필드가 모두 메모리에 정렬되어 있는 동안) 더 나은 선택이 될 것입니다.struct Bb필드는 홀수 오프셋에 위치합니다.구조 패킹은 구조 내부에 패딩 바이트가 삽입되지 않음을 의미합니다.

그러나 구조물 패킹은 일반적으로 특정 상황에서만 활성화됩니다.그것은 대부분의 프로그램에서 우려되는 것이 아닙니다.그리고 그것은 C 표준의 어떤 휴대용 구조물을 통해서도 제어할 수 없습니다.

이것 역시 짐작할 수 있는 부분이지만 대부분의 컴파일러는 패딩 바이트를 명시적으로 추가하지 않는 오정렬 옵션을 가지고 있습니다.그러면 일부 플랫폼에서는 런타임 수정(하드웨어 트랩)을 통해 즉시 액세스를 조정해야 합니다(해당 성능 패널티와 함께).내 기억으로는 HPUX가 이 범주에 속했습니다.따라서 첫 번째 구조는 정렬이 잘못된 컴파일러 옵션을 사용하더라도 필드가 여전히 정렬됩니다(왜냐하면 당신이 말했듯이 패딩은 끝에 있을 것이기 때문입니다.

언급URL : https://stackoverflow.com/questions/6968468/padding-in-structures-in-c

반응형