__attribute__的使用

__attribute__ 是 GCC 和 Clang 编译器中的一种语言扩展,用于给函数、变量、类型等添加属性,以便调整编译行为和优化。以下是一些常见的 __attribute__ 用法及其详细说明:

基本语法

__attribute__((attribute-list))

其中 attribute-list 是一个用逗号分隔的属性列表。

常见属性

以下是一些常用的 __attribute__ 属性及其作用:

  1. deprecated: 标记函数为已废弃,调用时会发出警告。
  2. unused: 标记变量为未使用,防止编译器发出未使用变量警告。
  3. noreturn: 标记函数不返回,编译器会进行相应优化。
  4. aligned: 指定变量的对齐方式。
  5. packed: 指示编译器为结构体优化空间,而不是默认对齐。
  6. format: 检查像 printf 、scanf 这类函数的格式字符串。

使用语法规则

1. 对于函数

属性应放在函数声明的尾部,但在函数定义时,属性必须放在返回类型之前,甚至可以放在声明的中间部分。

声明:属性在函数名之后

void warning_func() __attribute__((deprecated));

定义:属性在返回类型之后

__attribute__((deprecated)) void warning_func() {
    // 函数实现
}

2. 对于变量

属性可以放在变量声明或定义的末尾。

int unused_var __attribute__((unused));

3. 对于类型

属性可以放在类型定义的末尾。

typedef int int32 __attribute__((aligned(4)));

例子和详细解释

常见的 __attribute__ 用法

__attribute__((aligned(alignment))): 指定变量、结构体或联合体的对齐方式。

int x __attribute__((aligned(16)));  // x 对齐到 16 字节边界

__attribute__((packed)): 告诉编译器不要为结构体字段添加填充字节。

struct __attribute__((packed)) PackedStruct {
    char c;
    int i;
};

__attribute__((deprecated)): 标记函数或变量为不推荐使用,如果使用会产生警告。

void old_function() __attribute__((deprecated));

void old_function() {
    // implementation
}

__attribute__((noreturn)): 告诉编译器函数不会返回。

void fatal_error(const char *msg) __attribute__((noreturn));

void fatal_error(const char *msg) {
    // implementation
    exit(1);
}

__attribute__((format(archtype, string-index, first-to-check))): 检查函数的格式化字符串是否正确。例如,类似 printf 的函数。

void my_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));

void my_printf(const char *fmt, ...) {
    va_list args;
    va_start(args, fmt);
    vprintf(fmt, args);
    va_end(args);
}
#include <stdio.h>

void my_printf(__attribute__((format(printf, 1, 2))) const char *fmt, ...) {
    va_list args;
    va_start(args, fmt);
    vprintf(fmt, args);
    va_end(args);
}

void test_func() {
    my_printf("%s %d\n", "test"); // 编译时会检查格式字符串
}

__attribute__((unused)): 防止编译器对未使用的变量、函数或参数发出警告。

void func(int unused_param __attribute__((unused))) {
    // implementation
}

__attribute__((visibility("default"))): 设置符号的可见性,用于控制符号导出。

int public_variable __attribute__((visibility("default")));

__attribute__((cleanup(cleanup_function))): 指定一个函数,当变量超出作用域时自动调用此函数。

void cleanup_function(void *ptr) {
    free(*(void **)ptr);
}

void example() {
    void *ptr __attribute__((cleanup(cleanup_function))) = malloc(100);
    // 当 ptr 超出作用域时,cleanup_function 会被自动调用
}

__attribute__((section("section_name"))): 将变量或函数放入指定的段中。 

int special_variable __attribute__((section("special_section")));

__attribute__((regmap(3))): fastcall 是一种调用约定,它使用寄存器来传递函数参数,从而加快函数调用的速度。具体来说,regparm(3)表示最多使用三个寄存器来传递参数,这可以减少栈操作,提高性能。

#define fastcall __attribute__((regparm(3)))
fastcall int add(int a, int b) {
    return a + b;
}

 

示例1

以下是一个综合示例,演示了多种 __attribute__ 用法:

#include <stdio.h>
#include <stdlib.h>

// 定义一个对齐到 16 字节的结构体
struct __attribute__((aligned(16))) AlignedStruct {
    int a;
    char b;
};

// 定义一个打包的结构体
struct __attribute__((packed)) PackedStruct {
    char c;
    int d;
};

// 不推荐使用的函数
void old_function() __attribute__((deprecated));

void old_function() {
    printf("This is a deprecated function.\n");
}

// 不返回的函数
void fatal_error(const char *msg) __attribute__((noreturn));

void fatal_error(const char *msg) {
    fprintf(stderr, "Fatal error: %s\n", msg);
    exit(1);
}

// 格式化字符串检查函数
void my_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));

void my_printf(const char *fmt, ...) {
    va_list args;
    va_start(args, fmt);
    vprintf(fmt, args);
    va_end(args);
}

// 自动清理的变量
void cleanup_function(void *ptr) {
    free(*(void **)ptr);
}

void example() {
    void *ptr __attribute__((cleanup(cleanup_function))) = malloc(100);
    // 使用 ptr...
    // 当 ptr 超出作用域时,cleanup_function 会被自动调用
}

// 放入特定段的变量
int special_variable __attribute__((section("special_section")));

int main() {
    struct AlignedStruct as;
    struct PackedStruct ps;

    old_function();  // 使用不推荐的函数,会产生警告

    // 调用不会返回的函数
    // fatal_error("Something went wrong!");

    // 使用格式化字符串检查的函数
    my_printf("Hello, %s!\n", "world");

    example();

    // 使用放入特定段的变量
    printf("special_variable = %d\n", special_variable);

    return 0;
}

示例2

static const char __kstrtab_init_mm[]
__attribute__((section("__ksymtab_strings")))
= "init_mm";
解释
  1. static: 关键字 static 表示该变量的作用域仅限于当前文件,不能被其他文件访问。

  2. const char: const 表示该字符串是只读的,不可修改。char 类型表示这是一个字符数组。

  3. __kstrtab_init_mm[]: 变量名,表示这是一个字符数组。

  4. __attribute__((section("__ksymtab_strings"))): 将该变量放入名为 __ksymtab_strings 的段中。这个属性告诉编译器将该变量存储在指定的段中,而不是默认的段。

  5. = "init_mm": 变量的初始值,表示这是一个以 init_mm 作为内容的字符串。

section 属性用于将变量、函数等放入指定的段中。在内核开发和系统编程中,特定的段可以用于管理特定类型的数据。例如,__ksymtab_strings 段通常用于存储内核符号表的字符串。

#include <stdio.h>

// 将字符串放入名为 __ksymtab_strings 的段中
static const char __kstrtab_init_mm[] __attribute__((section("__ksymtab_strings"))) = "init_mm";
static const char __kstrtab_start_kernel[] __attribute__((section("__ksymtab_strings"))) = "start_kernel";

// 示例函数,用于展示如何使用这些字符串
void print_ksymtab_strings() {
    printf("Symbol: %s\n", __kstrtab_init_mm);
    printf("Symbol: %s\n", __kstrtab_start_kernel);
}

int main() {
    print_ksymtab_strings();
    return 0;
}
static const struct kernel_symbol __ksymtab_init_mm 
__attribute__((__unused__)) 
__attribute__((section("__ksymtab"), unused)) 
= { (unsigned long)&init_mm, __kstrtab_init_mm };

__attribute__((__unused__))__attribute__((unused))

是等价的,两者都用于防止编译器对未使用的变量、函数或参数发出警告。这两者仅用于告诉编译器“此变量/函数/参数可能未使用,不要发出警告”。

__attribute__((section("section_name"), unused)): 这个属性组合同时指定了变量或函数的段以及标记其为未使用。具体地:

section("section_name"):将变量或函数放入名为 section_name 的段中。

unused:防止编译器对未使用的变量、函数或参数发出警告。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值