__weak关键字和__attribute__

__weak关键字
__weak是一个c/c++编译器关键字,用于定义一个弱化符号。弱化符号是一种在链接阶段可以被覆盖的符号,允许多个同名符号存在于不同的目标文件中,而不会产生冲突。
 
当一个符号被声明为__weak时,它具有两个特性:
1、如果该符号在某个目标文件中被定义,那么这个定义将成为默认实现,并且可以在链接器阶段被覆盖
2、如果该符号在某个目标文件中未被定义,则该符号的默认实现将为NULL
 
__weak和__attribute__((weak))都是定义弱化符号的关键字或属性,作用一致
在GCC编译器中,__weak是一个预定义的关键字,用于标记弱化符号。而__attribuate__((weak))是一种编译器特性,可以通过编译器属性来指示一个符号为弱化符号
 
简单示例代码:
// weak.c
#include <stdio.h>

// 定义一个弱化的全局变量
int __attribute__((weak)) weak_variable = 10;

// 定义一个弱化的函数
void __attribute__((weak)) weak_function() {
    printf("Default implementation of weak_function\n");
}

int main() {
    // 使用弱化的全局变量
    printf("Weak variable: %d\n", weak_variable);

    // 调用弱化的函数
    weak_function();

    return 0;
}

// weak2.c
#include <stdio.h>

int weak_variable = 20;

void weak_function() {
    printf("weak2 implementation of weak_function\n");
}

gcc -o weak weak.c weak2.c
./weak

执行结果如下:
Weak variable: 20
weak2 implementation of weak_function

 

__attribute__ 

__attribute__可以用来指示执行特定的操作或者进行优化,一些常见的用法如下:
1、attribute((aligned(n))):指示编译器将变量或者类型对齐到n字节
#include <stdio.h>

struct align_struct {
    int a;
    char b;
} __attribute__((aligned(8)));

int main() {
    printf("Size of struct align_struct: %zu bytes\n", sizeof(struct align_struct));
    return 0;
}

运行结果:
Size of struct align_struct: 8 bytes
2、attribute((packed)):指示编译器不要增加结构体成员之间的任何填充字节,以节省空间
#include <stdio.h>

struct my_struct {
    int a;
    char b;
} __attribute__((packed));


int main() {
    printf("Size of struct my_struct: %zu bytes\n", sizeof(struct my_struct));
    return 0;
}

运行结果:
Size of struct my_struct: 5 bytes
 
3、attribute((section("name"))):可以将函数或变量放置到指定的段(section)中
如:
#define IRQ_DEFINE(__IrqId, __IrqHandle, __arg, __IrqName, __IrqFlags)        \
        __attribute__((section(".section_irq_table"))) struct irq_handler_struct   \
                _section_item_##__IrqId##_tlb = {                              \
                        .irqid = __IrqId,                                      \
                        .handler = __IrqHandle,                            \
                        .arg = __arg,                                        \
                        .irqname = __IrqName,                                  \
                        .irqflags = __IrqFlags,                                \
                }
在链接脚本中:
        . = ALIGN(8);
        .irq_table : {
                __section_irq_table_start = .;
                KEEP(*(SORT(.section_irq_table*)));
                __section_irq_table_end = .;
        }
此链接脚本的作用是将名为“.section_irq_table”的输入段中的内容与符号进行关联,并将它们放置到一个名为 ".irq_table" 的输出段中,并且确保其中的内容按地址顺序排列。同时,也定义了符号 __section_irq_table_start和 __section_irq_table_end,用于获取 ".section_irq_table" 段的起始和结束位置。
 
4、attribute((unused)):告诉编译器一个变量或者函数未被使用,避免编译器发出未使用变量或函数的警告
 
posted @ 2024-02-25 23:27  lethe1203  阅读(624)  评论(0编辑  收藏  举报