请问这个C语言语句怎么理解?#define __INIT __attribute__((unused, section("fs_vmn")))

vivikinomoto123STM32 2023-11-04 11:40:56 6929阅读 辽宁省沈阳市 辽宁大学(道义校区)
请问这个嵌入式C语言语句怎么理解?#define __INIT __attribute__((unused, section("fs_vmn")))
标签: #C语言#

提示:如果此问题没有解决您的需求,您可以点击 “我也要问” 在线咨询。 我也要问

若此问题存在违规行为,您可以点击 “举报”

3条回答

  • 徐靠
    2023-11-04 11:44:51 已采纳

    目前市面上多数的C/C++ IDE使用的编译工具链都是GCC或者LLVM,包括很多的商业IDE的工具链也是基于优化过的GCC或LLVM。而在用到一些高级编译器特性时,我们需要去了解一些编译器命令,比如GNU C的__attribute__,在uboot和Linux源码中会常用到此命令。

    __attribute__实际上是GCC的一种编译器命令,用来指示编译器执行实现某些高级操作。__attribute__可以设置函数属性(Function Attribute)、变量属性(Variable Attribute)和类型属性(Type Attribute)。LLVM也借用了GCC的__attribute__,并进行了扩展。

    函数属性可以帮助开发人员向函数声明中添加一些特性,这可以使编译器在错误检查方面增强。变量属性允许对变量或结构体成员使用特定的属性进行修饰,比如结构体的对齐控制。

    __attribute__的语法格式

    __attribute__ ((attribute-list))

    attribute的前面和后面都有两个下划线,后面紧跟两对元括弧, attribute-list是一个用逗号分隔开的属性列表。__attribute__ ((attribute-list))放于声明的尾部“;”之前。

    常用属性

    1、packed

    让编译器在编译时取消结构体的字节优化对齐,按照实际占用的字节数进行对齐。在某些场景用户不希望编译器对字节对齐进行调整,否则处理起来会比较麻烦,那么可以使用该属性。

    例如在源码中定义了两个结构

    struct unpacked_str

    {

    uint8_t x;

    uint16_t y;

    };

    struct packed_str

    {

    uint8_t x;

    uint16_t y;

    }__attribute__ ((packed));

    struct unpacked_str strupkd;

    struct packed_str strpkd;

    int main(void)

    {

    printf("%d", sizeof(strupkd));

    printf("%d", sizeof(strpkd));

    }

    使用clang编译,运行时分别输出为4和3。

    2、aligned

    规定变量或结构体成员最小对齐格式,以字节为单位。让用户自行决定变量的对齐字节数,比如一些处理器架构要求向量表需要按照规定的对齐地址放置,这时用户就需要进行控制了。

    在代码中定义了一个32位变量:

    uint32_t var_in_8bytes __attribute__((aligned(8)));

    查看链接后的map映射文件,可以验证对齐的字节数和地址。

    同样,你也可以使用默认的对齐方式。如果aligned后面不紧跟一个指定的数字值,那么编译器将依据你的目标机器情况使用最大最有益的对齐方式。

    struct mystr

    {

    int16_t a[3];

    } __attribute__ ((aligned));

    3、section

    section控制变量或函数在编译时的段名。在嵌入式软件开发时用的非常多,比如有外扩Flash或RAM时,需要将变量或函数放置到外扩存储空间,可以在链接脚本中指定段名来操作。在使用MPU(存储保护)的MCU编程时,需要对存储器划分区域,将变量或代码放置到对应的区域,通常也是通过段操作来实现。

    const int identifier[3] __attribute__ ((section ("ident"))) = { 1,2,3 };

    void myfunction (void) __attribute__ ((section ("ext_function")))

    上述代码分别在编译后,数组和函数所在的段分别为“indent”和“ext_function”。

    4、unused

    意味着函数或变量很可能未被使用,编译器不会针对这个函数产生警告,可以将其声明在在函数实现中没有使用过的参数上,例如:

    int main(int argc __attribute__((unused)), char **argv)

    { ...}

    5、used

    此属性附加到具有静态存储的变量,意味着即使该变量看起来没有被引用,也必须保留该变量。否则在链接的时候链接器发现某个变量未被引用,会将此变量优化掉。

    6、weak

    若两个或两个以上全局符号名字一样,而其中之一声明为weak symbol(弱符号),则这些全局符号不会引发重定义错误。当普通符号存在时,链接器会忽略掉弱符号,如果不存在普通符号,则使用弱符号。

    更多的__attribute__属性可以参考GCC手册,在我们需要使用到编译器一些高级特性的时候,可以在手册中查找。

    3564 举报
  • 铅笔画童年
    2023-11-04 11:42:13


    第一个参数unused在gcc手册中有相关的解释:
    unused:This attribute, attached to a function, means that the function is meant to be
            possibly unused. GCC will not produce a warning for this function.
    ===============================================================================
    used: This attribute, attached to a function, means that code must be emitted for the
           function even if it appears that the function is not referenced. This is useful,
           for example, when the function is referenced only in inline assembly.


    表示该函数或变量可能不使用,这个属性可以避免编译器产生警告信息

    64 举报
  • 平淡最真
    2023-11-04 11:43:48

    第二个参数section控制变量或函数在编译时的段名。在嵌入式软件开发时用的非常多,比如有外扩Flash或RAM时,需要将变量或函数放置到外扩存储空间,可以在链接脚本中指定段名来操作。在使用MPU(存储保护)的MCU编程时,需要对存储器划分区域,将变量或代码放置到对应的区域,通常也是通过段操作来实现。

    const int identifier[3] __attribute__ ((section ("ident"))) = { 1,2,3 };

    void myfunction (void) __attribute__ ((section ("ext_function")))

    上述代码分别在编译后,数组和函数所在的段分别为“indent”和“ext_function”。

    480 举报
103电阻是多少
STM32 38434人阅读
Linux内核printfk打印信息怎么打开
Linux驱动 8460人阅读

快速提问,在线解答

1

描述需求

填写需求概要标题,补充详细需求

2

耐心等

等待网友或网站工作人员在线解答

3

巧咨询

还有疑问?及时追问回复

立即咨询