sourcetip

C에서 "포장된" 구조는 무엇입니까?

fileupload 2023. 6. 7. 23:06
반응형

C에서 "포장된" 구조는 무엇입니까?

나는 마이크로칩 C30 컴파일러용으로 작성된 C 코드를 살펴보고 있으며 종종 다음과 같이 정의된 구조를 봅니다.

typedef struct __attribute__((__packed__)) 
{
    IP_ADDR     MyIPAddr;               // IP address
    IP_ADDR     MyMask;                 // Subnet mask
    IP_ADDR     MyGateway;              // Default Gateway
        // etc...
} APP_CONFIG;

packed가 무슨 뜻입니까?

구조가 정의되면 컴파일러는 패딩(실제 데이터가 없는 공간)을 추가할 수 있으므로 구성원이 CPU에 더 쉽게 액세스할 수 있는 주소 경계에 속합니다.

예를 들어 32비트 CPU에서 32비트 멤버는 효율적으로 액세스(읽기 및 쓰기)하려면 4바이트의 배수 주소에서 시작해야 합니다.다음 구조 정의는 두 구성원 사이에 16비트 패딩을 추가하여 두 번째 구성원이 적절한 주소 경계에 속하도록 합니다.

struct S {
    int16_t member1;
    int32_t member2;
};

32비트 아키텍처에서 위의 구조를 기억하는 구조는 (~ = 패딩):

+---------+---------+
| m1 |~~~~|   m2    |
+---------+---------+

구조물이 채워질 때 이러한 패딩은 삽입되지 않습니다.컴파일러는 정렬되지 않은 데이터 멤버를 추출하고 쓰기 위해 더 많은 코드(더 느리게 실행됨)를 생성해야 합니다.

동일한 구조가 패킹되면 메모리에 다음과 같이 나타납니다.

+---------+---------+
| m1 |   m2    |~~~~
+---------+---------+

컴파일러가 구성원 간에 패딩을 추가하지 않도록 지시합니다.struct.

예를 들어, 이 페이지를 참조하십시오.

예를 들어 구조물의 패딩과 패킹 구조물의 개념을 설명하겠습니다.

그리고 왜 포장이 필요한지 알아보겠습니다.

패딩:

struct eg_struct
{
           unsigned char abc;
           unsigned int  xyz;
}

16비트 아키텍처에서 구조가 위와 같이 선언될 때, 변수는abc주소가 할당될 것입니다.다음 주소가 변수에 할당되지 않았습니다.xyz대신 하나의 추가 바이트가 추가되고 다음 주소가 변수에 할당됩니다.xyz.

결국, 구조는 다음과 같습니다.

struct eg_struct
{
           unsigned char abc;
           unsigned char paddedbytes[1];
           unsigned int  xyz;
}

패딩을 사용하면 멤버 변수의 주소를 마이크로컨트롤러에서 쉽게 액세스할 수 있습니다.단점은 사진에 들어오는 불필요한 바이트입니다.

포장:

속성 "을 사용하여 동일한 구조가 선언된 경우packed변수 뒤에 추가 바이트가 추가되지 않습니다.abc.

포장이 필요한 한 가지 예를 들어 보겠습니다.

일부 구조물이 저장되는 EEPROM과 인터페이스된 마이크로컨트롤러를 생각해 보십시오.

EEPROM에 기록하는 기능을 다음과 같이 상상해 보십시오.

Write_EEPROM(EEPROM address, Ram address, Byte count);

패킹을 하지 않으면 추가 패딩된 바이트가 EEPROM의 공간을 차지하게 되어 아무 소용이 없습니다.

_attribute__((__packed__))는 "더 빨리 만들기 위해 패딩을 삽입하지 않음"을 의미하며, "정렬을 유지하기 위해 정렬을 삽입하지 않음"을 의미할 수도 있습니다.

명시적으로 호출되지 않은 한 가지는 패킹이 일반적으로 사전 정의된 필드 구조와 일치하도록 수행된다는 것입니다.예를 들어 네트워크 인터페이스의 하위 계층에서는 네트워크 시스템 간에 일련의 바이트가 교환됩니다.데이터를 수신한 후에는 데이터를 쉽게 조작할 수 있도록 높은 수준의 구조로 매핑해야 합니다.이것은 구조가 바이트에 직접 매핑되도록 일반적으로 패딩이 필요하지 않은 경우입니다.

네트워크 데이터 교환에는 바이트 엔디언 문제도 포함됩니다(즉, 거의 모든 네트워크 데이터는 소스 및 대상 시스템의 엔디언과 관계없이 빅 엔디언 형식을 사용합니다).

또한 Cortex-M0 코어는 32비트가 아닌 주소의 32비트 데이터에 액세스할 수 없으므로 이러한 경우 네트워킹 코드를 작성하는 데 주의해야 합니다.

구조체 선언 중에 패킹을 사용하면 컴파일러는 동일한 구조체의 멤버에 패딩을 추가하지 않습니다.아래는 자체 설명이 가능한 코드 및 출력 예제입니다.

$ cat structure_packed.c
#include <stdio.h>

typedef struct __attribute__((__packed__))
{
        char a;
        int ai;
        char ac;
}A;

struct B
{
        char b;
        int bi;
        char bc;
};

int main()
{
         A a;
        struct B b;
        int c;
        printf("size of struct A: %lu, addr a: %p, addr ai: %p, addr ac: %p\n", sizeof(a), &(a.a), &(a.ai), &a.ac);
        printf("size of struct B: %lu, addr b: %p, addr bi: %p, addr bc: %p\n", sizeof(b), &(b.b), &(b.bi), &b.bc);
        printf("addr of c: %p\n", &c);
        return 0;
}

컴파일

$ gcc structure_packed.c -o structure_packed

실행|출력

$ ./structure_packed
size of struct A: 6, addr a: 0x7ffc6f177ed6, addr ai: 0x7ffc6f177ed7, addr ac: 0x7ffc6f177edb
size of struct B: 12, addr b: 0x7ffc6f177edc, addr bi: 0x7ffc6f177ee0, addr bc: 0x7ffc6f177ee4
addr of c: 0x7ffc6f177ed0

언급URL : https://stackoverflow.com/questions/5473189/what-is-a-packed-structure-in-c

반응형