weak和alias

一、强符号和弱符号

在C语言中,如果多个模块定义同名全局符号时,链接器认为函数和已初始化的全局变量(包括显示初始化为0)是强符号,未初始化的全局变量是弱符号。

根据这个定义,Linux链接器使用下面的规则来处理多重定义的符号名:

1.不允许有多个同名的强符号

2.如果有一个强符号和多个弱符号同名,那么选择强符号

3.如果有多个弱符号同名,有些编译器从这些弱符号中任意选择一个,有些编译器选择占用内存最大的那个符号

符号链接原理:链接器发现同时存在弱符号和强符号,优先选择强符号,如果发现不存在强符号,只存在弱符号,则选择弱符号

二、weak的使用

对于初始化的各种函数,我们不确定其他地方是否有这个函数,但是我们不得不用这个函数,即在初始化过程中必须得有这个函数。在这种情况下,可以使用__attribute__关键字的weak属性来声明一个弱符号。

//weak.c
#include <stdio.h>
// int fun1()
// {
    // printf("new %s\n",__FUNCTION__);
    // return 0;
// }
int main()
{
  fun1();
  return 0;
}
//test.c
#include <stdio.h>
int fun1() __attribute__((weak));

int fun1() 
{
  printf("%s\n",__FUNCTION__);
  return 0;
}

在注释掉weak.c中的fun1时,编译运行

gcc -o weak weak.c teat.c
./weak

输出结果为:

fun1

接下来,我们把对fun1的注释去掉,同样编译运行,运行结果为:

new fun1


三、alias的使用

在使用weak声明弱符号之后,我们需要将每个弱符号函数都定义为一个空函数,如果每个函数都分开写的话,重复量很大,也比较浪费时间。所以可以用alias属性来给每个函数起别名。

#include <stdio.h>

int fun1() 
{
  printf("%s\n",__FUNCTION__);
  return 0;
}
 
int fun() __attribute__((alias("fun1")));

int main()
{
  fun();
  return 0;
}

代码中fun的别名是fun1,所以运行结果为:

fun1

四、weak和alias结合使用

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

int fun1() 
{
  printf("%s\n",__FUNCTION__);
  return 0;
}
 
int fun2() __attribute__((weak, alias("fun1")));
int fun3() __attribute__((weak, alias("fun1")));
//attribute.c
#include <stdio.h>

int fun2() 
{
  printf("%s\n",__FUNCTION__);
  return 0;
}

int main()
{
  fun2();
  fun3();
  return 0;
}

fun2是强符号,fun3没有初始化,而fun2和fun3的别名均为fun1,运行结果为:

fun2
fun1

猜你喜欢

转载自www.cnblogs.com/zzdbullet/p/9883507.html