C 언어에서 __attribute__ 사용

이 기사는  C 언어-CSDN 블로그___attribute__에서 __attribute__를 사용하여 _qlexcel의 열을 재인쇄합니다.

C 언어에서 __attribute__의 사용법을 기록하는 데 사용됩니다.

1. 소개

GNU C의 주요 기능은 __attribute__ 메커니즘입니다. __attribute__는 함수 속성( Function Attribute), 변수 속성(Variable Attribute) 및 유형 속성(Type Attribute)을 설정할 수 있습니다 .

__attribute__의 쓰기 기능은 다음과 같습니다. __attribute__ 앞뒤에 두 개의 밑줄이 있고 그 뒤에 원래 대괄호 쌍이 있으며 해당 __attribute__ 매개변수가 대괄호 안에 있습니다.

__attribute__ 구문 형식: __attribute__ ((attribute-list))

__attribute__ 키워드는 구조(struct) 또는 공용체(union)에 대한 속성을 설정할 수도 있습니다. 약 6개의 매개변수 값을 설정할 수 있습니다.

__attribute__ 매개변수를 사용할 때 매개변수 앞뒤에 "__"(밑줄 2개)를 추가할 수도 있습니다. 헤더 파일에 같은 이름의 매크로 정의가 있습니다.

2. __attribute__의 매개변수 소개

1, 정렬 

다음과 같이 개체의 정렬 형식(바이트)을 지정합니다.

struct S {
 
short b[3];
 
} __attribute__ ((aligned (8)));
 
 
typedef int int32_t __attribute__ ((aligned (8)));

이 선언은 컴파일러가 struct S 또는 int32_t 유형의 변수가 8바이트 정렬로 할당되도록 보장하도록 합니다.

위에서 언급했듯이 정렬 형식을 수동으로 지정할 수 있으며 마찬가지로 기본 정렬을 사용할 수 있습니다. 정렬 바로 뒤에 지정된 숫자 값이 오지 않으면 컴파일러는 대상 시스템에 대해 가장 크고 가장 유익한 정렬을 사용합니다. 예를 들어:

struct S {
 
short b[3];
 
} __attribute__ ((aligned));

여기서 sizeof(short)의 크기가 2byte라면 S의 크기는 6이다. 2의 거듭제곱 값을 취하여 값이 6보다 크거나 같으면 값이 8이므로 컴파일러는  S 유형 의 정렬을 8바이트로 설정합니다.

얼라인드 속성은 설정되는 객체가 더 많은 공간을 차지하도록 하는 반면, 패킹을 사용하면 객체가 차지하는 공간을 줄일 수 있습니다.

속성 속성의 효율성은 링커와도 관련이 있다는 점에 유의해야 합니다.링커가 최대 16바이트 정렬만 지원하는 경우 이 시점에서 32바이트 정렬을 정의하는 것은 쓸모가 없습니다.

2, 포장

        이 특성을 사용하여 구조체 또는 공용체 유형을 정의하고 해당 유형의 각 변수에 대한 메모리 제약 조건을 설정합니다. 컴파일러에게 컴파일 과정에서 구조의 최적화된 정렬(1바이트 정렬 사용)을 취소하고 실제 차지하는 바이트 수에 따라 정렬하도록 지시하는 것인데, 이는 GCC 고유의 구문입니다. 이 함수는 운영 체제와 관련이 없으며 컴파일러와 관련이 있습니다.gcc 컴파일러는 컴팩트 모드가 아닙니다.저는 Windows에 있으며 vc 컴파일러는 컴팩트하지 않지만 tc 컴파일러는 컴팩트합니다.

        다음 예에서, packed_struct 유형의 변수 배열에 있는 값은 서로 근접하지만 내부 멤버 변수 s는 "팩"되지 않습니다. 내부 멤버 변수를 패킹하려면 unpacked-struct도 "팩"됩니다. Packed는 해당 제약 조건에 사용해야 합니다.

    struct unpacked_struct
    {
          char c;
          int i;
    };
             
    struct packed_struct
    {
         char c;
         int  i;
         struct unpacked_struct s;
    }__attribute__ ((__packed__));

如:

    在TC下:struct my{ char ch; int a;}      sizeof(int)=2;sizeof(my)=3;(紧凑模式)
     
    在GCC下:struct my{ char ch; int a;}     sizeof(int)=4;sizeof(my)=8;(非紧凑模式)
     
    在GCC下:struct my{ char ch; int a;}__attrubte__ ((packed))        sizeof(int)=4;sizeof(my)=5
下面的例子中使用__attribute__ 属性定义了一些结构体及其变量,并给出了输出结果和对结果的分析。代码为:

    struct p
    {
        int a;
        char b;
        short c;
     
    }__attribute__((aligned(4))) pp;
     
    struct m
    {
        char a;
        int b;
        short c;
    }__attribute__((aligned(4))) mm;
     
    struct o
    {
        int a;
        char b;
        short c;
    }oo;
     
    struct x
    {
        int a;
        char b;
        struct p px;
        short c;
    }__attribute__((aligned(8))) xx;
     
    int main()
    {           
        printf("sizeof(int)=%d,sizeof(short)=%d.sizeof(char)=%d\n",sizeof(int)
                                                    ,sizeof(short),sizeof(char));
        printf("pp=%d,mm=%d \n", sizeof(pp),sizeof(mm));
        printf("oo=%d,xx=%d \n", sizeof(oo),sizeof(xx));
        return 0;
    }

输出结果:

sizeof(int)=4,sizeof(short)=2.sizeof(char)=1

pp=8,mm=12

oo=8,xx=24

分析:都是字节对齐的原理

3、에서

절대 위치 지정, Flash에서 변수 또는 함수를 절대적으로 찾거나 RAM에서 찾을 수 있습니다.

1)、定位到flash中,一般用于固化的信息,如出厂设置的参数,上位机配置的参数,ID卡的ID号,flash标记等等

    const u16 gFlashDefValue[512] __attribute__((at(0x0800F000))) = {0x1111,0x1111,0x1111,0x0111,0x0111,0x0111};//定位在flash中,其他flash补充为00
    const u16 gflashdata__attribute__((at(0x0800F000))) = 0xFFFF;

 

2)、定位到RAM中,一般用于数据量比较大的缓存,如串口的接收缓存,再就是某个位置的特定变量

u8 USART2_RX_BUF[USART2_REC_LEN] __attribute__ ((at(0X20001000)));//接收缓冲,最大USART_REC_LEN个字节,起始地址为0X20001000.


注意:

1)、绝对定位不能在函数中定义,局部变量是定义在栈区的,栈区由MDK自动分配、释放,不能定义为绝对地址,只能放在函数外定义。

2)、定义的长度不能超过栈或Flash的大小,否则,造成栈、Flash溢出。

4, 섹션

        섹션에 관해서는 RO RI ZI라고 해야 합니다. ARM 컴파일러가 컴파일된 후 코드는 여러 섹션으로 나뉩니다. RO 섹션(ReadOnly)은 코드 섹션과 상수를 저장하고 RW 섹션(ReadWrite)은 읽고 쓸 수 있는 정적을 저장합니다. 변수 및 전역 변수 ZI 섹션(ZeroInit)은 0으로 초기화된 RW 세그먼트에 저장되는 변수입니다.
        따라서 이 문서의 일반적인 의미는 명확합니다. __attribute__((section("section_name"))), 함수 또는 함수의 데이터를 지정된 이름 "section_name"에 해당하는 섹션에 넣는 것입니다.

1) 컴파일 타임에 변수의 세그먼트를 지정합니다.

__attribute__((section("name")))
RealView Compilation Tools for µVision Compiler Reference Guide Version 4.0 
 
Home > Compiler-specific Features > Variable attributes > __attribute__((section("name"))) 
 
4.5.6. __attribute__((section("name")))
Normally, the ARM compiler places the objects it generates in sections like data and bss. However, you might require additional data sections or you might want a variable to appear in a special section, for example, to map to special hardware. The section attribute specifies that a variable must be placed in a particular data section. If you use the section attribute, read-only variables are placed in RO data sections, read-write variables are placed in RW data sections unless you use the zero_init attribute. In this case, the variable is placed in a ZI section.
 
Note
This variable attribute is a GNU compiler extension supported by the ARM compiler.
 
Example
/* in RO section */
const int descriptor[3] __attribute__ ((section ("descr"))) = { 1,2,3 };
/* in RW section */
long long rw[10] __attribute__ ((section ("RW")));
/* in ZI section *
long long altstack[10] __attribute__ ((section ("STACK"), zero_init));/

2) 컴파일 타임에 함수의 세그먼트 지정

__attribute__((section("name")))
RealView Compilation Tools for µVision Compiler Reference Guide Version 4.0 
 
Home > Compiler-specific Features > Function attributes > __attribute__((section("name"))) 
 
4.3.13. __attribute__((section("name")))
The section function attribute enables you to place code in different sections of the image.
 
Note
This function attribute is a GNU compiler extension that is supported by the ARM compiler.
 
Example
In the following example, Function_Attributes_section_0 is placed into the RO section new_section rather than .text.
 
void Function_Attributes_section_0 (void) __attribute__ ((section ("new_section")));
void Function_Attributes_section_0 (void)
{
    static int aStatic =0;
    aStatic++;
}
In the following example, section function attribute overrides the #pragma arm section setting.
 
#pragma arm section code="foo"
  int f2()
  {
      return 1;
  }                                  // into the 'foo' area
 
  __attribute__ ((section ("bar"))) int f3()
  {
      return 1;
  }                                  // into the 'bar' area
 
  int f4()
  {
      return 1;
  }                                  // into the 'foo' area
#pragma arm section

5. 복수속성, 겸용

u8 FileAddr[100] __attribute__ ((section ("FILE_RAM"), zero_init,aligned(4)));    

Supongo que te gusta

Origin blog.csdn.net/qq_48709036/article/details/123130788
Recomendado
Clasificación