在Linux開發(fā)環(huán)境中油宜,有強符號和弱符號掂碱,符號簡單來說就是函數(shù)、變量的名字慎冤,對于全局(非局部疼燥、非static)的函數(shù)和變量,能不能重名是有一定規(guī)矩的蚁堤,強悴了、弱符號就是針對這些全局函數(shù)和變量來說的。
強符號與弱符號
在C語言中违寿,函數(shù)和初始化的全局變量(包括顯示初始化為0)是強符號,未初始化的全局變量是弱符號熟空。其規(guī)則如下:
- 同名的強符號只能定義一次藤巢,否則編譯錯誤。
- 同名的強弱符號同時存在時息罗,以強符號為準掂咒。
- 多個弱符號相同時,則從多個弱符號中任選一個迈喉。
聲明弱符號
弱符號的聲明可采用兩種方式:
- 使用
__attribute__((weak))
修飾:
void __attribute__((weak)) func(void)
or
__attribute__((weak)) void func(void)
or
void func(void)__attribute__((weak))
- 使用
#pragma weak
修飾:
#pragma weak func
舉個例子
main.c
#include <stdio.h>
void __attribute__((weak)) func(void)
{
printf("Can't find the define of %s!\n", __FUNCTION__);
}
int main(int argc, char **argv)
{
func();
return 0;
}
編譯輸出:
$ gcc main.c -o test && ./test
Can't find the define of func!
Note:對于上述函數(shù)的聲明绍刮,還可以這樣寫:
void __attribute__((weak)) func(void); void func(void) { printf("Can't find the define of %s!\n", __FUNCTION__); }
還可以這樣寫:
void func(void)__attribute__((weak)); void func(void) { printf("Can't find the define of %s!\n", __FUNCTION__); }
但是下面的寫法就是導致編譯失敗:
void func(void)__attribute__((weak)) { printf("Can't find the define of %s!\n", __FUNCTION__); }
func.c
#include <stdio.h>
void func(void)
{
printf("I‘m the define of %s!\n", __FUNCTION__);
}
編譯輸出:
$ gcc main.c func.c -o test && ./test
I'm the define of func!
結論:同名函數(shù)的強符號和弱符號同時存在時挨摸,以強符號為準孩革,弱符號失去作用。因此在實際開發(fā)中得运,若函數(shù)func
還未ready膝蜈,在調用func
函數(shù)的主函數(shù)中對其聲明為__attribute__((weak))
后可以使主函數(shù)編譯通過,否則主函數(shù)因無法link函數(shù)func
而編譯失敗熔掺。
__weak的含義
有時候在代碼中可以看到會用到__weak
饱搏,其實__weak
是一個宏定義,在Linux代碼中可以見其定義在include/linux/compiler_attributes.h
中:
#define __weak __attribute__((weak))
它常用于函數(shù)和變量的聲明和函數(shù)的定義置逻,是GNU compiler的擴展推沸,被ARM compiler支持,可以將一個函數(shù)聲明為weak券坞,當沒有其他同名函數(shù)聲明時調用weak鬓催,有其他同名函數(shù)時調用其他同名函數(shù)。