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
五、使用weak和alias对可执行文件的影响
先看使用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")));
int fun4() __attribute__((weak, alias("fun1")));
int fun5() __attribute__((weak, alias("fun1")));
int fun6() __attribute__((weak, alias("fun1")));
int fun7() __attribute__((weak, alias("fun1")));
int fun8() __attribute__((weak, alias("fun1")));
int fun9() __attribute__((weak, alias("fun1")));
int fun10() __attribute__((weak, alias("fun1")));
int fun11() __attribute__((weak, alias("fun1")));
int fun12() __attribute__((weak, alias("fun1")));
int fun13() __attribute__((weak, alias("fun1")));
//attribute.c
#include <stdio.h>
int main()
{fun2();fun3();fun4();fun5();fun6();fun7();fun8();fun9();fun10();fun11();fun12();fun13();return 0;
}
链接之后生成的文件大小为:8987。那么如果将weak和alias去掉,同时将这么多fun全部重新定义,
//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")));
// int fun4() __attribute__((weak, alias("fun1")));
// int fun5() __attribute__((weak, alias("fun1")));
// int fun6() __attribute__((weak, alias("fun1")));
// int fun7() __attribute__((weak, alias("fun1")));
// int fun8() __attribute__((weak, alias("fun1")));
// int fun9() __attribute__((weak, alias("fun1")));
// int fun10() __attribute__((weak, alias("fun1")));
// int fun11() __attribute__((weak, alias("fun1")));
// int fun12() __attribute__((weak, alias("fun1")));
// int fun13() __attribute__((weak, alias("fun1")));
//attribute.c
#include <stdio.h>int fun2()
{printf("%s\n",__FUNCTION__);return 0;
}
int fun3()
{printf("%s\n",__FUNCTION__);return 0;
}
int fun4()
{printf("%s\n",__FUNCTION__);return 0;
}
int fun5()
{printf("%s\n",__FUNCTION__);return 0;
}
int fun6()
{printf("%s\n",__FUNCTION__);return 0;
}
int fun7()
{printf("%s\n",__FUNCTION__);return 0;
}
int fun8()
{printf("%s\n",__FUNCTION__);return 0;
}
int fun9()
{printf("%s\n",__FUNCTION__);return 0;
}
int fun10()
{printf("%s\n",__FUNCTION__);return 0;
}
int fun11()
{printf("%s\n",__FUNCTION__);return 0;
}
int fun12()
{printf("%s\n",__FUNCTION__);return 0;
}
int fun13()
{printf("%s\n",__FUNCTION__);return 0;
}int main()
{fun2();fun3();fun4();fun5();fun6();fun7();fun8();fun9();fun10();fun11();fun12();fun13();return 0;
}
在这种情况下,生成的可执行文件的大小为:9473。可见利用weak和alias可以节省可执行文件的占用空间。
六、函数有形参的情况
如果函数有形参,具体情况是什么呢?看下面代码,如果别名函数有形参,
//test_attribute.c
#include <stdio.h>int fun1(int a, int b)
{a = 3;printf("%s, %d\n", __FUNCTION__, a);return 0;
}int fun2() __attribute__((weak, alias("fun1")));
//attribute.c
#include <stdio.h>
int main()
{fun2();return 0;
}
运行结果为:
fun1, 3
另外,还有一种情况,强符号函数声明有形参
//test_attribute.c
#include <stdio.h>int fun1(int a, int b)
{a = 3;printf("%s, %d\n", __FUNCTION__, a);return 0;
}int fun2() __attribute__((weak, alias("fun1")));
int fun3() __attribute__((weak, alias("fun1")));
int fun4() __attribute__((weak, alias("fun1")));
int fun5() __attribute__((weak, alias("fun1")));
int fun6() __attribute__((weak, alias("fun1")));
int fun7() __attribute__((weak, alias("fun1")));
int fun8() __attribute__((weak, alias("fun1")));
int fun9() __attribute__((weak, alias("fun1")));
int fun10() __attribute__((weak, alias("fun1")));
int fun11() __attribute__((weak, alias("fun1")));
int fun12() __attribute__((weak, alias("fun1")));
int fun13() __attribute__((weak, alias("fun1")));
//attribute.c
#include <stdio.h>int fun2(int a, int b)
{a = 5;printf("%s, %d\n", __FUNCTION__, a);return 0;
}
int main()
{int a;int b;fun2(a, b);return 0;
}
运行结果为:
fun2, 5
个人理解:
在利用weak和alias设置弱符号函数的时候,实际是将fun2指向了fun1,
而如果另外定义了同样的fun2后,它属于强符号,那么test_sttribute.c声明中的fun2指向的是这个新定义的fun2,
这种实现是对函数名地址的改变,而函数内的形参在设置weak和alias可以不用写入
weak和alias相关推荐
- __attribute__ 之weak,alias属性
Weak Alias 跟 Weak Reference 完全没有任何关系,不过是我在看到 Weak Reference 的时候想到的而已. Weak Alias 是 gcc 扩展里的东西,实际上是函数 ...
- 关于GCC属性中的弱符号(weak symbol)
关于弱符号的解释: 若两个或两个以上全局符号(函数或变量名)名字一样,而其中之一声明为weak symbol(弱符号),则这些全局符号不会引发重定义错误.链接器会忽略弱符号,去使用普通的全局符号来解析 ...
- __attribute__ 总结
attribute是GNU C特色之一,在iOS用的比较广泛.系统中有许多地方使用到. attribute可以设置函数属性(Function Attribute ).变量属性(Variable Att ...
- gcc: weak_alias如何使用
本文主要说明weak和alias是什么和如何使用它 __attribute__是用来说明函数的属性,weak和alias分别是两个属性. (一)强符号和弱符号: 强符号:已经初始化的全局变量和未被we ...
- GCC中的弱符号与强符号
转载自 https://www.cnblogs.com/kernel_hcy/archive/2010/01/27/1657411.html 我们经常在编程中碰到一种情况叫符号重复定义.多个目标文件中 ...
- S5PV210-uboot解析(三)-start_armboot解析
start_armboot解析 start_armboot函数在lib_arm/board.c文件里,除了函数本身,还有一些用到了的定义和宏.S5PV210-uboot解析-start.S解析(二)- ...
- 弱符号与弱引用 -> 程序员的自我修养 第3,4章笔记
1. 在程序中声明并使用节名 先看下面一段有意思的程序 #include <stdio.h>__attribute__((section("abcd"))) int s ...
- (转)C语言家族扩展
(转)C语言家族扩展 翻译: 5.1--5.6 林峰 5.7--5.20 董溥 5.21--5.26 王聪 5.27--5.34 刘洋 5.35--5.43 贾孟树 致谢:感谢陈老师指出其中的一些错误 ...
- _attribute用法总结
attribute是GNU C特色之一,在iOS用的比较广泛.系统中有许多地方使用到. attribute可以设置函数属性(Function Attribute ).变量属性(Variable Att ...
- __attribute__((weak))是什么意思
最近在阅读tcmalloc代码时发现使用了很多__attribute__((weak)),上网搜了以下有所了解. 弱符号: 若两个或两个以上全局符号(函数或变量名)名字一样,而其中之一声明为weak ...
最新文章
- Nginx学习3:反向代理实例
- python自动化办公都能做什么菜-Python 让我再次在女同学面前长脸了!(真实案例)...
- This version of the rendering library is more recent than your version of IntelliJ IDEA.
- 团队项目第一篇——NABCD
- Map对象与实体类Object对象转换
- Ubuntu安装minicom串口工具
- 【android自定义控件】LinearLayout定义ActionBar样式
- Python OpenCV 美女换装,图像处理取经之旅第 19 天
- php input type='button' 颜色,HTML5 input新增type属性color颜色拾取器的实例代码
- 网页连接mysql教程_网页怎么连接到数据库?
- 分式求二阶导数_第12讲 典型例题与练习参考解答:导数的基本运算法则与高阶导数...
- Ubuntu安装deb包
- sql之分组TOPN
- 编译原理——自下而上的语法分析方法(LR分析法)
- 电商平台数据仓库搭建02-Hadoop集群搭建
- 2019面试/笔试题(算法题)总结
- Latex 绘制函数图像
- 《论语》全译——公冶长篇第五
- 怎么用显卡计算_显卡性能的软件 3dmark怎么用
- nCode:DesignLife案例教程一
热门文章
- 《关于雪糕刺客与雪糕护卫激发中国人的创作灵感这件事》
- 【python文字游戏】飞花令
- 网站地图是什么,怎么制作和查看网站的地图呢?
- 在Ubuntu5.1中安装NVIDIA TNT2 M64老式显卡驱动程序..
- Nature Reviews Microbiology | 土壤微生物组与同一健康
- Array Shrinking(区间DP)
- 举个栗子!Tableau 技巧(185):实现多度量嵌套排序
- 武汉第一职业教育中心计算机技能高考,武汉市第一职业教育中心
- Java8 CompletableFuture(2)回调函数 thenApply thenAccept thenRun
- 关于反转的总结(C/C++)